iptables에 REDIRECT 규칙을 추가한 후 다른 리디렉션 포트를 표시하는 Tcpdump

iptables에 REDIRECT 규칙을 추가한 후 다른 리디렉션 포트를 표시하는 Tcpdump

에서 수신 대기 중인 kubernetes 클러스터 NodePort로 클라이언트 트래픽을 전달하려고 합니다 192.168.1.100.30000.

클라이언트가 요청해야 하므로 192.168.1.100.8000iptables에 다음 REDIRECT 규칙을 추가했습니다.

iptables -t nat -I PREROUTING -p tcp --dst 192.168.1.100 --dport 8000 -j REDIRECT --to-port 30000

그런 다음 컬을 실행 192.168.1.100:8000하지만 tcpdump에는 다른 포트가 표시됩니다.

# tcpdump -i lo -nnvvv host 192.168.1.100 and port 8000
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
[Interface: lo] 20:39:22.685968 IP (tos 0x0, ttl 64, id 20590, offset 0, flags [DF], proto TCP (6), length 40)
[Interface: lo]     192.168.1.100.8000 > 192.168.1.100.49816: Flags [R.], cksum 0xacda (correct), seq 0, ack 3840205844, win 0, length 0
[Interface: lo] 20:39:37.519256 IP (tos 0x0, ttl 64, id 34221, offset 0, flags [DF], proto TCP (6), length 40)

나는 tcpdump가 다음과 같은 것을 보여줄 것으로 기대합니다.

192.168.1.100.8000 > 192.168.1.100.30000

그러나 에 프로세스가 나열되지 않아 연결 거부 오류가 표시되고 발생합니다 192.168.1.100.49816.

192.168.1.100.8000 > 192.168.1.100.49816

테스트 환경을 사용하고 있으므로 원격 장치에 액세스할 수 없으므로 curliptables REDIRECT 경로를 테스트하는 데 사용하고 있습니다.

REDIRECT 규칙을 추가하면 tcpdump가 지정된 포트가 아닌 다른 포트로 트래픽을 리디렉션하는 이유가 있습니까?

편집하다:

@AB 제안 후에 다음 OUTPUT 규칙을 추가했습니다.

iptables -t nat -I OUTPUT -d 192.168.1.100 -p tcp --dport 8000 -j REDIRECT --to-port 30000

컬이 더 진행되면 OUTPUT 체인의 패킷 수가 증가합니다(그러나 PREROUTING REDIRECT 체인 패킷은 증가하지 않았습니다).

2       10   600 REDIRECT   tcp  --  *      *       0.0.0.0/0            192.168.1.100         tcp dpt:8000 redir ports 30000

그러나 다음과 같은 오류가 발생합니다.

# curl -vk https://192.168.1.100:8000/v1/api
* About to connect() to 192.168.1.100 port 8000 (#0)
*   Trying 192.168.1.100...
* Connected to 192.168.1.100 (192.168.1.100) port 8000 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* NSS error -12263 (SSL_ERROR_RX_RECORD_TOO_LONG)
* SSL received a record that exceeded the maximum permissible length.
* Closing connection 0
curl: (35) SSL received a record that exceeded the maximum permissible length.

또한, 원격 시스템 네트 추가를 시도했는데, 이번에는 실행 후 PREROUTING REDIRECT CHAIN ​​패킷 수가 증가합니다 remotesystem curl ...(그러나 OUTPUT CHAIN은 증가하지 않습니다).

2       34  2040 REDIRECT   tcp  --  *      *       0.0.0.0/0            172.16.128.1         tcp dpt:8000 redir ports 30000

오류:

# ip netns exec remotesystem curl -vk https://192.168.1.100:8000/v1/api
* About to connect() to 192.168.1.100 port 8000 (#0)
*   Trying 192.168.1.100...
* Connection timed out
* Failed connect to 192.168.1.100:8000; Connection timed out
* Closing connection 0
curl: (7) Failed connect to 192.168.1.100:8000; Connection timed out

답변1

명확하게 말하면 OP의 테스트는 원격 시스템이 아닌 시스템 192.168.1.100에서 자체적으로 수행되며 이것이 문제의 원인입니다. 이 경우에는 일치하는 NAT 규칙이 없기 때문에 포트가 변경되지 않았지만 원격 시스템에서 수행했다면 일치했을 것입니다.

아래 회로도는 패킷에서 작업 순서가 수행되는 방식을 보여줍니다.

Netfilter 및 일반 네트워킹의 패킷 흐름

그 이유는 Linux에서 NAT가 작동하는 방식입니다.iptablesnat새로운 conntrack 흐름(따라서 NEW 상태임)의 첫 번째 패킷에 대해서만 테이블 의 패킷을 봅니다 .

이 규칙은 원격 시스템에서 잘 작동합니다. 이 경우 표시되는 첫 번째 패킷은 수신 패킷입니다.

to port 8000 --> AF_PACKET (tcpdump) --> conntrack --> nat/PREROUTING (iptables REDIRECT): to port 30000
--> routing decision --> ... --> local process receiving on port 30000

동일한 흐름의 모든 후속 패킷에는 conntrack이 포트 변경(또는 응답을 위한 포트 전환)을 직접 처리하고 테이블의 iptables 규칙을 건너뜁니다 nat(회로도: 연결 nat에만 참조된 테이블에 기록됨 NEW). 따라서 (응답 패킷 부분을 건너뛰고) 다음 수신 패킷은 대신 다음을 수행합니다.

to port 8000 --> AF_PACKET (tcpdump) --> conntrack: to port 30000
--> routing decision --> ... --> local process receiving on port 30000

시스템 자체에 대한 테스트의 경우 첫 번째 패킷은 들어오는 패킷이 아니라 나가는 패킷입니다. 대신 나가는 lo인터페이스를 사용하면 이런 일이 발생합니다.

local process client curl --> routing decision --> conntrack --> nat/OUTPUT (no rule here)
--> reroute check --> AF_PACKET (tcpdump) --> to port 8000

이제 이 패킷은 인터페이스에서 루프백되어 lo더 이상 연결의 첫 번째 패킷이 아닌 패킷으로 다시 나타나므로 위와 같이 두 번째 경우를 따릅니다. conntrack 단독으로 NAT를 처리하고 호출하지 않습니다 nat/PREROUTING. NAT를 수행하기 전 단계에서 지시되지 않은 경우를 제외하고는 다음과 같습니다.

to port 8000 --> AF_PACKET (tcpdump) --> conntrack
--> routing decision --> ... -->nolocal process receiving on port8000

포트 8000에서 수신 대기 중인 항목이 없으므로 OS는 TCP RST를 다시 보냅니다.

이것이 로컬 시스템에서 작동하려면 체인 REDIRECT에 규칙도 추가되어야 합니다 nat/OUTPUT.

iptables -t nat -I OUTPUT -d 192.168.1.100 -p tcp --dport 8000 -j REDIRECT --to-port 30000

추가 참고사항

  • 사례가 원격 사용을 위한 것이라면 로컬 시스템에서 테스트하지 마세요. 테스트에서 통과하는 규칙은 동일하지 않습니다. 이는 테스트가 현실을 반영하지 못하게 만듭니다.

    다른 시스템을 사용할 수 없는 경우를 대비해 네트워크 네임스페이스를 사용하여 포켓 원격 시스템을 만드세요. OP의 nat/PREROUTING규칙 만 있고 수행하는 시스템에서 작동해야 하는 예 curl http://192.168.1.100/(DNS가 필요하지 않음):

    ip netns add remotesystem
    ip link add name vethremote up type veth peer netns remotesystem name eth0
    ip address add 192.0.2.1/24 dev vethremote
    ip -n remotesystem address add 192.0.2.2/24 dev eth0
    ip -n remotesystem link set eth0 up
    ip -n remotesystem route add 192.168.1.100 via 192.0.2.1
    ip netns exec remotesystem curl http://192.168.1.100:8000/
    
  • tcpdump및 NAT

    tcpdumpAF_PACKET위 회로도의 단계 에서 발생합니다 . 즉, 수신의 경우 매우 초기이고 송신의 경우 매우 늦습니다. 이는 원격 시스템의 경우 작동 중이더라도 포트 30000을 캡처하지 않음을 의미합니다. 로컬 시스템의 경우 nat/OUTPUT규칙이 추가되면 포트 30000을 캡처합니다.

    NAT를 수행할 때 표시되는 주소/포트를 맹목적으로 신뢰하지 마십시오 tcpdump. 상황과 캡처가 발생하는 위치에 따라 다릅니다.

관련 정보