아래 그림과 같이 이렇게 리눅스 커널을 통해 트래픽을 라우팅하는 것이 가능한가요? 동일한 IP 범위를 사용하여 "내부" 네트워크 외부의 장치의 정확한 복사본을 에뮬레이트하면서 상대방이 동일한 IP를 가지고 있다는 사실을 모른 채 내부 및 외부 장치가 서로 통신할 수 있도록 하고 싶습니다.
예: 장치 그런 다음 응답은 중개자에게 다시 전송되고 IP 192.168.2.5의 장치 X로 전송됩니다.
나는 이것이 네트워크 네임스페이스를 통해 가능하고 효율적인 가장을 허용한다는 것을 알고 있습니다. 그러나 저는 네임스페이스 사용을 피하고 대신 다양한 트래픽 방향에 대해 다른 라우팅 테이블과 같은 것을 사용하고 싶습니다. 가능합니까?
올바르게 이해했다면 IP 범위가 중복되어 NAT를 사용할 수 없습니다. 맞습니까?
답변1
토폴로지
먼저 네트워크 인터페이스를 구성합니다 middleman
. 나는 당신이 시스템 콘솔에 로그인했거나 또는 inner
네트워크와 관련되지 않은 인터페이스를 통해 액세스했다고 가정합니다 outer
. 이 답변의 목적을 위해 우리는 인터페이스 middleman-eth0
가 middleman
"내부" 네트워크에 연결되고 middleman-eth1
"외부" 네트워크에 연결되어 있다고 가정합니다. 이는 다음과 같은 네트워크 토폴로지를 제공합니다.
전달 활성화
패킷 전달이 활성화되어 있는지 확인해야 합니다 middleman
.
sysctl -w net.ipv4.ip_forward=1
빈 netfilter 구성으로 시작해야 합니다. 실행하면 iptables-save
출력이 생성되지 않습니다.
인터페이스 구성
이를 위해 middleman-eth0
둘 다 middleman-eth1
동일한 네트워크 구성을 갖습니다.
ip addr add 192.168.2.1/24 dev middleman-eth0
ip addr add 192.168.2.1/24 dev middleman-eth1
이것이 이상해 보인다고 생각했다면, 맞습니다! 현재 라우팅 테이블은 middleman
다음과 같습니다.
192.168.2.0/24 dev middleman-eth1 proto kernel scope link src 192.168.2.1
192.168.2.0/24 dev middleman-eth0 proto kernel scope link src 192.168.2.1
이것은 특별히 유용하지 않습니다.
VRF 구성
우리는 Linux를 사용하여 "가상 라우팅 및 전달eth0
"("VRF"). 이를 통해 들어오는 트래픽이 들어오는 트래픽과 다른 라우팅 테이블을 볼 수 있도록 시스템에 여러 개의 격리된 라우팅 도메인을 만들 수 있습니다 eth1
.
먼저 VRF 인터페이스를 만듭니다.
ip link add vrf-inner type vrf table 100
ip link set vrf-inner up
ip link add vrf-outer type vrf table 200
ip link set vrf-outer up
이 명령은 두 개의 VRF 장치를 설정하여 각 장치를 특정 라우팅 테이블과 연결합니다.
다음으로 각 물리적 인터페이스를 VRF 장치에 연결합니다.
ip link set dev middleman-eth0 master vrf-inner
ip link set dev middleman-eth1 master vrf-outer
이러한 변경 후에는 이제 기본 라우팅 테이블이 비어 있습니다.
middleman# ip route show
<no output>
middleman-eth0
표 100에는 ("내부" 네트워크)와 관련된 규칙이 나와 있습니다.
middleman# ip route show table 100
broadcast 192.168.2.0 dev middleman-eth0 proto kernel scope link src 192.168.2.1
192.168.2.0/24 dev middleman-eth0 proto kernel scope link src 192.168.2.1
local 192.168.2.1 dev middleman-eth0 proto kernel scope host src 192.168.2.1
broadcast 192.168.2.255 dev middleman-eth0 proto kernel scope link src 192.168.2.1
middleman-eth1
표 200에는 ("외부" 네트워크)에 대한 규칙이 나와 있습니다.
middleman# ip route show table 200
broadcast 192.168.2.0 dev middleman-eth1 proto kernel scope link src 192.168.2.1
192.168.2.0/24 dev middleman-eth1 proto kernel scope link src 192.168.2.1
local 192.168.2.1 dev middleman-eth1 proto kernel scope host src 192.168.2.1
broadcast 192.168.2.255 dev middleman-eth1 proto kernel scope link src 192.168.2.1
이 시점에서 실제로 아래와 같이 두 개의 연결이 끊긴 네트워크가 있습니다.
"내부" 네트워크의 호스트는 192.168.2.1에 접속할 수 있으며 접속됩니다 middleman-eth0
. "외부" 네트워크의 호스트는 다음을 수행할 수 있습니다.반품192.168.2.1로 연락하면 통화 중일 것입니다 middleman-eth1
.
두 사람이 만난 장소
이제 우리가 해야 할 일은 어느 쪽이든 192.168.3.0/24
다른 쪽의 주소를 사용하여 노드에 연결할 수 있도록 매핑을 설정하는 것뿐입니다.
192.168.3.0/24
먼저 모든 노드에 다음을 통해 네트워크로 라우팅된다는 사실을 알려야 합니다 middleman
. 즉, "내부" 및 "외부" 네트워크 모두의 모든 노드에서 다음이 필요합니다.
ip route add 192.168.3.0/24 via 192.168.2.1
위에서는 middleman
(a) 192.168.3.0/24
범위 내의 주소를 192.168.2.0/24
범위로 매핑하고 (b) 연결을 라우팅할 때 올바른 라우팅 테이블이 사용되는지 확인해야 합니다. (a)를 달성하기 위해 몇 가지 규칙을 만들 수 있습니다 NETMAP
.
iptables -t nat -A PREROUTING -d 192.168.3.0/24 -j NETMAP --to 192.168.2.0/24
iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -j NETMAP --to 192.168.3.0/24
(b)를 구현하기 위해 먼저 수신 인터페이스에 따라 패킷을 표시합니다.
iptables -t mangle -A PREROUTING -i middleman-eth0 -d 192.168.3.0/24 -j MARK --set-mark 100
iptables -t mangle -A PREROUTING -i middleman-eth1 -d 192.168.3.0/24 -j MARK --set-mark 200
그런 다음 이러한 태그는 라우팅 테이블을 선택하는 데 사용됩니다.
ip rule add prio 100 fwmark 100 lookup 200
ip rule add prio 200 fwmark 200 lookup 100
테이블 100에는 "내부" 네트워크에 대한 규칙이 있고 테이블 200에는 "외부" 네트워크에 대한 규칙이 있으므로 이러한 규칙은 "인터페이스에 도착하는 패킷의 경우 middleman-eth0
결정과 관련된 라우팅 테이블을 사용하십시오 middleman-eth1
"라고 말하고 그 반대의 경우도 마찬가지입니다. .
튀는 공을 따라가다
이 모든 작업이 완료된 후 192.168.2.10
"내부" 네트워크의 노드가 ping을 시도하는 경우 192.168.3.10
:
- 라우팅 항목 으로 인해
192.168.3.0/24 via 192.168.2.1
패킷이 중개자에게 라우팅됩니다. - 패킷 도착
middleman-eth0
- 패킷은
MANGLE
테이블 체인 에 도착PREROUTING
하고 fwmark를 다음으로 설정합니다.100
- 패킷이
NAT
테이블 체인에 도달하여PREROUTING
대상에 매핑됩니다.192.168.2.10
fwmark 100 lookup 200
패킷은 규칙을 준수하는 라우팅 하위 시스템으로 들어갑니다.- 라우팅 테이블 200에서 히트하여
192.168.2.0/24 dev middleman-eth1
커널이 이를 장치로 보냅니다.middleman-eth1
- 패킷이
NAT
테이블 체인 에 도착POSTROUTING
하고 해당 소스가 에 매핑됩니다192.168.3.10
. - 패킷은 주소가 "외부" 노드에 도착합니다
192.168.2.10
. - ...심호흡을 해보세요...
- 외부 노드가 응답을 보냅니다.
192.168.3.10
- 답장 도착
middleman-eth1
- 응답은
MANGLE
테이블 체인 에 도착PREROUTING
하고 fwmark를 다음으로 설정합니다.200
- 응답은
NAT
테이블 체인에 도착PREROUTING
하고 대상에 매핑됩니다.192.168.2.10
fwmark 200 lookup 100
응답은 규칙을 준수하는 라우팅 하위 시스템으로 이동합니다.- 라우팅 테이블 100에서는
192.168.2.0/24 dev middleman-eth0
규칙과 일치하므로 커널이 이를 장치로 보냅니다.middleman-eth0
- 응답은
NAT
테이블 체인 에 도착POSTROUTING
하고 해당 소스는 테이블 체인에 매핑됩니다.192.168.3.10
- 응답은
192.168.2.10
원래 요청에 대한 응답을 확인하는 "내부" 노드에 도달합니다.
확인하다
"내부" 노드 0( 192.168.2.10
)에서 주소를 사용하여 "외부" 노드 0에 ping을 시도하면 내부 노드 0에서 실행하면 다음이 표시됩니다 192.168.3.10
.tcpdump -nn -i any icmp
07:01:58.125370 innernode0-eth0 Out IP 192.168.2.10 > 192.168.3.10: ICMP echo request, id 12999, seq 1, length 64
07:01:58.125533 innernode0-eth0 In IP 192.168.3.10 > 192.168.2.10: ICMP echo reply, id 12999, seq 1, length 64
우리는 middleman
봤다:
07:01:58.125440 middleman-eth0 In IP 192.168.2.10 > 192.168.3.10: ICMP echo request, id 12999, seq 1, length 64
07:01:58.125459 middleman-eth1 Out IP 192.168.3.10 > 192.168.2.10: ICMP echo request, id 12999, seq 1, length 64
07:01:58.125514 middleman-eth1 In IP 192.168.2.10 > 192.168.3.10: ICMP echo reply, id 12999, seq 1, length 64
07:01:58.125518 middleman-eth0 Out IP 192.168.3.10 > 192.168.2.10: ICMP echo reply, id 12999, seq 1, length 64
"외부" 노드 0에는 다음이 표시됩니다.
07:01:58.125489 outernode0-eth0 In IP 192.168.3.10 > 192.168.2.10: ICMP echo request, id 12999, seq 1, length 64
07:01:58.125497 outernode0-eth0 Out IP 192.168.2.10 > 192.168.3.10: ICMP echo reply, id 12999, seq 1, length 64
그래서 우리는 당신의 목표를 달성했다고 생각합니다!
나는 사용했다미니넷이 구성을 테스트해 보세요. 내 테스트 환경에 대한 전체 소스 코드를 찾을 수 있습니다.여기. 이 구성에 대한 실습 비디오가 있습니다.여기.
고쳐 쓰다
AB가 댓글에서 지적했듯이 이 구성에는 뭔가 문제가 있습니다! 기본적으로 커널의 연결 추적 논리는 소스/대상 주소와 소스/대상 포트만 살펴봅니다. innernode0
포트 4000에서 포트 80으로 의 연결은 outernode0
다음과 같습니다.동일한연결은 반대 방향의 연결입니다... 즉, 모든 노드의 포트 80에서 실행되는 웹 서버가 있다고 가정하면 다음 두 명령은 다음과 같습니다.
innernode0# curl --local-port 4000 192.168.3.10
그리고:
outernode0# curl --local-port 4000 192.168.3.10
다음 위치에 단일 연결 추적 항목이 생성됩니다 middleman
.
middleman# conntrack -L
tcp 6 118 TIME_WAIT src=192.168.2.10 dst=192.168.3.10 sport=4000 dport=80 src=192.168.2.10 dstroot@mininet-vm:/proc/net=192.168.3.10 sport=80 dport=4000 [ASSURED] mark=0 use=1
conntrack 하위 시스템에 이러한 연결을 구별하는 방법을 알려줍니다. 테이블의 체인에 한 쌍의 규칙을 추가하여 CT
이를 수행 할 수 있습니다.PREROUTING
RAW
iptables -t raw -A PREROUTING -s 192.168.2.0/24 -i middleman-eth0 -j CT --zone-orig 100
iptables -t raw -A PREROUTING -s 192.168.2.0/24 -i middleman-eth1 -j CT --zone-orig 200
이러한 규칙이 적용되면 이제 conntrack 테이블에서 두 개의 개별 연결을 볼 수 있습니다.
middleman# conntrack -L
tcp 6 113 TIME_WAIT src=192.168.2.10 dst=192.168.3.10 sport=4000 dport=80 zone-orig=200 src=192.168.2.10 dst=192.168.3.10 sport=80 dport=40568 [ASSURED] mark=0 use=1
tcp 6 112 TIME_WAIT src=192.168.2.10 dst=192.168.3.10 sport=4000 dport=80 zone-orig=100 src=192.168.2.10 dst=192.168.3.10 sport=80 dport=4000 [ASSURED] mark=0 use=1