在实际应用场景下,我们可能需要建立一个测试环境,既能接线上流量,又不希望影响线上业务,这个时候流量镜像就派上用场。它会将一个网络接口中的流量复制到另外一个网络接口中,然后在后者上分发,而前者不受影响。
在上图中我们可以看到,复制过来的流量会被转换——转换成vxlan协议的UDP流量。这个现象就导致测试环境的接口和生产环境不一致——这并不是我们希望的——我们希望部署在测试环境和生产环境上的代码或程序是一样的。
为了解决这个问题,我们需要加一个中间层:把UDP的vxlan协议转回去,并分发到测试环境。
现在我们在AWS上完成上述设计。
创建一个100.0.0.0/24的VPC,名字叫TrafficMirrorVpc。
我们将分配一个Public类型子网TrafficMirrorSourcePublicSubnet,用于接收互联网流量。它下面实例的流量将会被复制到名字叫TrafficMirrorAdapterPrivateSubnet子网下的实例。经过转换,流量会被发送给TrafficMirrorTargetPrivateSubnet子网下的实例。我们在TrafficMirrorSourcePublicSubnet和TrafficMirrorTargetPrivateSubnet子网下部署的实例的程序是一样的,这样前者模拟线上环境,后者模拟测试环境。
子网名称 | IPv4/CIDR | 区域 |
---|---|---|
TrafficMirrorSourcePublicSubnet | 100.0.0.0/28 | eu-west-1a |
TrafficMirrorAdapterPrivateSubnet | 100.0.0.16/28 | eu-west-1a |
TrafficMirrorTargetPrivateSubnet | 100.0.0.32/28 | eu-west-1a |
这儿需要注意一点,被镜像流量的实例需要是基于AWS Nitro System的。适配的类型可以见:https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/instance-types.html#ec2-nitro-instances。我们选择相对便宜的t3.nano类型来做测试。 我们会对公网下的TrafficMirrorSourceEC2开启自动分配公有IP的功能。因为我们既要在互联网上对其发送流量,也需要把它作为跳板机跳转到其他两个私有网络下的EC2上,以方便部署代码。
实例名 | 所属子网 | 实例类型 | 是否自动分配公有IP |
---|---|---|---|
TrafficMirrorSourceEC2 | TrafficMirrorSourcePublicSubnet | t3.nano | 是 |
TrafficMirrorAdapterEC2 | TrafficMirrorAdapterPrivateSubnet | t3.nano | 否 |
TrafficMirrorTargetEC2 | TrafficMirrorTargetPrivateSubnet | t3.nano | 否 |
这个不是必须步骤。主要是为了让TrafficMirrorAdapterPrivateSubnet和TrafficMirrorTargetPrivateSubnet子网下EC2实例可以访问外网,以方便部署代码。
创建一个给Private网络的路由。
然后配置路由
因为默认的ACL只允许22端口访问,而TrafficMirrorSourcePublicSubnet子网下机器需要开放80端口以供外网测试,且TrafficMirrorAdapterPrivateSubnet需要响应4789端口的UDP请求,所以我们将对各个子网的ACL进行定制。
主要开启22端口和80端口,源地址选择任意。它主要给TrafficMirrorSourcePublicSubnet和TrafficMirrorTargetPrivateSubnet使用。
这儿需要注意的是,针对两个子网开启所有TCP连接,否则SSH会失败。
主要开放UDP协议的4789端口,是给TrafficMirrorAdapterPrivateSubnet使用。
通过公网下的EC2跳板机,我们登录到TrafficMirrorAdapterEC2,执行下面的命令
sudo yum update -y
sudo yum install git -y
sudo yum install go -y
sudo yum install libpcap-devel -y
go env GOPATH
export HOME=~
echo 'export GOPATH=$HOME/go' >>~/.bash_profile
source ~/.bash_profile
mkdir -p $GOPATH"/src/vxlan-to-http-request"
wget https://github.com/aws-samples/http-requests-mirroring/raw/main/main.go -P $GOPATH"/src/vxlan-to-http-request"
cd $GOPATH"/src/vxlan-to-http-request"
go mod init vxlan-to-http-request
go get "github.com/google/gopacket"
go mod tidy
go build ./
go install vxlan-to-http-request
sudo ip link add vxlan0 type vxlan id 1 dev eth0 dstport 4789
sudo ip link set vxlan0 up
这儿特别需要注意下倒数第二行 vxlan id 1这个,需要和后续创建的流量镜像Session的VNI值一致(即也设置为1)。 然后这么执行程序(其中100.0.0.37是TrafficMirrorTargetEC2的IP)
sudo ./vxlan-to-http-request -destination "http://100.0.0.37" -filter-request-port "80"
我们只检测80端的入站流量
我们需要把流量镜像到Adapter层EC2的网络接口。
源我们选TrafficMirrorSourceEC2的网络接口
我们在生产环境TrafficMirrorSourceEC2和测试环境TrafficMirrorTargetEC2上启动一个简单的http服务。
sudo python3 -m http.server 80
可以看到两个环境收到了一致的请求。
整个配置过程其实比较简单。只是因为要测试,且对ACL、安全组要求比较严格,导致很多设置。 最最需要注意的是我们在创建镜像会话时,要记住VNI的值,然后保证其和下面${TrafficMirroringVNI}值一致。
sudo ip link add vxlan0 type vxlan id ${TrafficMirroringVNI} dev eth0 dstport 4789
sudo ip link set vxlan0 up