다이어그램부터 시작하겠습니다.
Workstation -> TrafficShaper -> Internet
| ^
V |
LinuxProxy ---------
내 트래픽 셰이퍼에는 패킷을 다른 호스트(그림의 LinuxProxy)로 전환할 수 있는 기능이 있습니다. 이더넷 대상 MAC 주소를 LinuxProxy의 인터페이스로 설정하고 LinuxProxy가 패킷을 수신할 네트워크에 패킷을 배치하여 이를 수행합니다. LinuxProxy는 패킷에 대해 원하는 작업을 자유롭게 수행할 수 있으며, 모든 응답은 TrafficShaper가 이더넷 대상으로 설정된 네트워크에 배치되어야 합니다.
예를 들어 워크스테이션이 TCP SYN을 www.google.com으로 보낸다고 가정해 보겠습니다. 패킷은 TrafficShaper로 이동한 다음 LinuxProxy로 보냅니다. LinuxProxy는 SYN-ACK(TrafficShaper로 이동한 다음 워크스테이션으로 돌아옴)로 응답을 시도하지만 LinuxProxy가 어떤 이더넷 대상 MAC 주소를 사용할지 알 수 없다는 문제가 있습니다. TrafficShaper의 데이터 인터페이스에는 IP 바인딩이 없으므로 트래픽을 TrafficShaper로 직접 다시 보내는 경로를 설정할 수 없다는 의미라고 가정합니다. 설상가상으로 TrafficShaper의 MAC 주소는 요청하는 워크스테이션에 따라 변경될 수 있습니다. 원래 보낸 MAC 주소로 응답 패킷을 보내려면 LinuxProxy가 필요합니다. TCP 연결에 대해 이 작업을 수행하려는 경우 각 연결의 MAC 주소를 기억하고 항상 해당 MAC에 응답 패킷을 보낼 수 있는 방법이 있습니까? 아니면 소스 IP 주소의 MAC 주소를 기억하고 해당 IP에 응답할 때 항상 해당 MAC을 사용합니까?
tcpdump를 사용하여 업데이트합니다(tcpdump -n -nn -i eth1 -e -vv 포트 80 또는 arp):
1) 워크스테이션이 HTTP 요청을 할 때 LinuxProxy에서 라우팅을 구성하지 않으면 LinuxProxy는 다음을 확인합니다.
16:02:02.382023 TrafficShaper:VirtualInterfaceX > LinuxProxy:eth1, ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 122, id 30174, offset 0, flags [DF], proto TCP (6), length 52)
Workstation:IP.21875 > RandomWebserver.80: Flags [S], cksum 0x2ffb (correct), seq 1782577522, win 65535, options [mss 1460,nop,wscale 2,nop,nop,sackOK], length 0
라우팅이 없고 LinuxProxy가 어떤 인터페이스에서 응답할지 모르기 때문에 SYN-ACK도 표시되지 않습니다. dmesg에서 다음 내용도 볼 수 있습니다.
[177553.396852] device eth1 entered promiscuous mode
[177555.286091] IPv4: martian source LinuxProxyIP from WorkstationIP, on dev eth1
[177555.294651] ll header: 00000000: XX XX XX XX XX RT.1....5.:...
[177560.529102] device eth1 left promiscuous mode
2) LinuxProxy가 어떤 인터페이스에 응답할지 알 수 있도록 경로를 추가해 보겠습니다(트래픽 셰이퍼에는 IP가 없으므로 여기에 인터페이스를 넣겠습니다).
route add default dev eth1
이제 내 tcpdump에 따르면 LinuxProxy는 워크스테이션의 IP에 대해 ARP를 시도하지만 TrafficShaper는 ARP에 응답하지 않고 ARP를 다른 쪽 끝으로 전달하지 않습니다. (어쨌든 워크스테이션 MAC은 쓸모가 없습니다)
16:41:14.800321 TrafficShaper:VirtualInterfaceX > LinuxProxy:eth1, ethertype IPv4 (0x0800), length 62: (tos 0x0, ttl 122, id 30787, offset 0, flags [DF], proto TCP (6), length 48)
Workstation:IP.21975 > RandomWebserver.80: Flags [S], cksum 0xc8cf (correct), seq 2481765147, win 65535, options [mss 1460,nop,nop,sackOK], length 0
16:41:14.800432 LinuxProxy:eth1 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has Workstation:IP tell 10.89.14.11, length 28
16:41:15.800890 LinuxProxy:eth1 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has Workstation:IP tell 10.89.14.11, length 28
16:41:16.802797 LinuxProxy:eth1 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has Workstation:IP tell 10.89.14.11, length 28
16:41:17.792513 TrafficShaper:VirtualInterfaceX > LinuxProxy:eth1, ethertype IPv4 (0x0800), length 62: (tos 0x0, ttl 122, id 30788, offset 0, flags [DF], proto TCP (6), length 48)
Workstation:IP.21975 > RandomWebserver.80: Flags [S], cksum 0xc8cf (correct), seq 2481765147, win 65535, options [mss 1460,nop,nop,sackOK], length 0
3) TrafficShaper에서 MAC를 하드코딩하면 이것이 작동하는지 확인하기 위해 가짜 ARP 항목을 만들고 경로를 해당 IP로 변경했습니다. 참고: TrafficShaper에는 각각 자체 MAC이 있는 약 50개의 가상 인터페이스가 있고 많은 워크스테이션이 다음을 통해 로드 밸런싱되기 때문에 프로덕션에서는 이 작업을 수행할 수 없습니다.
ip neighbor add FAKE_IP lladdr TrafficShaper:VirtualInterfaceX dev eth1
route del default dev eth1
route add default gw FAKE_IP
이제 3방향 핸드셰이크가 완료되었습니다.
16:52:17.077903 TrafficShaper:VirtualInterfaceX > LinuxProxy:eth1, ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 122, id 31076, offset 0, flags [DF], proto TCP (6), length 52)
Workstation:IP.22033 > RandomWebserver.80: Flags [S], cksum 0x5a9f (correct), seq 3325648471, win 65535, options [mss 1460,nop,wscale 2,nop,nop,sackOK], length 0
16:52:17.078024 LinuxProxy:eth1 > TrafficShaper:VirtualInterfaceX, ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52)
RandomWebserver.80 > Workstation:IP.22033: Flags [S.], cksum 0x99ab (incorrect -> 0x18fa), seq 1232307723, ack 3325648472, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
16:52:17.157231 TrafficShaper:VirtualInterfaceX > LinuxProxy:eth1, ethertype IPv4 (0x0800), length 60: (tos 0x0, ttl 122, id 31077, offset 0, flags [DF], proto TCP (6), length 40)
Workstation:IP.22033 > RandomWebserver.80: Flags [.], cksum 0xfbdb (correct), seq 1, ack 1, win 53248, length 0
16:52:17.165426 LinuxProxy:eth1 > TrafficShaper:VirtualInterfaceX, ethertype IPv4 (0x0800), length 54: (tos 0x0, ttl 64, id 20208, offset 0, flags [DF], proto TCP (6), length 40)
... extras removed ...
각 워크스테이션 IP가 TrafficShaper의 특정 가상 인터페이스로 부하 분산된다는 것을 알고 있습니다. 주어진 워크스테이션 IP에 대한 응답 패킷을 패킷을 수신한 MAC으로 다시 보낼 수 있는 방법이 있다면 문제가 해결될 것입니다. 저는 현재 WorkstationIP->MAC 매핑을 사전에 저장한 다음 패킷을 다시 보낼 때 해당 MAC을 조회할 수 있는 방법이 있는지 알아보기 위해 netfilter 문서를 살펴보고 있습니다.