
에서 수신 대기 중인 kubernetes 클러스터 NodePort로 클라이언트 트래픽을 전달하려고 합니다 192.168.1.100.30000
.
클라이언트가 요청해야 하므로 192.168.1.100.8000
iptables에 다음 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
테스트 환경을 사용하고 있으므로 원격 장치에 액세스할 수 없으므로 curl
iptables 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 규칙이 없기 때문에 포트가 변경되지 않았지만 원격 시스템에서 수행했다면 일치했을 것입니다.
아래 회로도는 패킷에서 작업 순서가 수행되는 방식을 보여줍니다.
그 이유는 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 --> ... -->
no
local process receiving on port
8000
포트 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
및 NATtcpdump
AF_PACKET
위 회로도의 단계 에서 발생합니다 . 즉, 수신의 경우 매우 초기이고 송신의 경우 매우 늦습니다. 이는 원격 시스템의 경우 작동 중이더라도 포트 30000을 캡처하지 않음을 의미합니다. 로컬 시스템의 경우nat/OUTPUT
규칙이 추가되면 포트 30000을 캡처합니다.NAT를 수행할 때 표시되는 주소/포트를 맹목적으로 신뢰하지 마십시오
tcpdump
. 상황과 캡처가 발생하는 위치에 따라 다릅니다.