임의의 TCP 응답 패킷에 fwmark 반영을 강제로 적용할 수 있습니까?

임의의 TCP 응답 패킷에 fwmark 반영을 강제로 적용할 수 있습니까?

TCP 소켓 연결 응답에서 fwmark가 누락되는 문제를 해결한 사람이 있습니까?

배경:

요청이 수신된 동일한 인터페이스에서 응답이 전송되도록 해야 하며, 다른 수단(예: 소스 기반 라우팅)으로 구별할 수 없는 네트워크 아웃바운드 인터페이스를 지원해야 합니다.이 답변정책 기반 라우팅에 대해 살펴보겠습니다. 처음에는 내 상황에 맞지 않는 것 같았습니다.별말씀을요(tcpdump를 사용하여 인터페이스의 트래픽을 관찰하고 iptables에 양방향으로 패킷 메타데이터를 기록하도록 지시) 이 시점에서 내가 바라던 대로 들어오는 패킷이 실제로 들어오는 인터페이스에 따라 태그가 지정되는 것을 볼 수 있습니다. 그러나 나가는 패킷은 동일한 태그를 유지하지 않습니다! 소켓 연결에서 간단한 핑(ICMP 에코)으로 테스트 사례를 단순화했으며 fwmark가 누락되었음을 깨달았을 때 더 많은 연구를 수행하여 발견했습니다."fwmark_reflect" sysctl 매개변수. 이를 활성화하면 단순화된 테스트 사례의 문제가 해결되었지만 물론 sysctl은 "커널에서 생성된 IP 패킷, 이와 관련된 사용자 소켓이 없습니다"에만 영향을 주기 때문에 원래 문제에는 도움이 되지 않습니다. SSH와 같은 소켓 연결...

추가 지원 세부정보:

iptables 패킷 표시 규칙:

-A 사전 라우팅-i ens3 -j mark --set-mark 1 -A 사전 라우팅-i ens4 -j MARK --set-mark 2

라우팅 규칙(필사적으로 무엇이든 시도하고 있기 때문에 일부는 중복됨): #ip 규칙 목록 0: 모두에서 로컬 찾기 0: 모든 fwmark 0x1에서 찾기 mgmt 0: 모든 fwmark 0x2에서 찾기 cust 10: 모든 fwmark 0x1에서 mgmt 20 찾기: 모든 fwmark 0x2에서 cust 32766 찾기: 모두에서 기본 32767 찾기: 모두에서 기본값 65536 찾기: 모든 fwmark 0x2 oif ens4에서 cust 찾기

#ip route list table mgmt
  default via 10.100.16.1 dev ens3 
#ip route list table cust

기본적으로 221.194.47.243 mark 2는 10.100.16.1 dev ens4 ip 경로를 통해 획득됩니다. 221.194.47.243은 10.100.16.1 dev ens4 src 10.100.16.13 mark 2를 통해 획득됩니다.

요청 및 응답을 반영하는 Iptables의 로그 출력(전체 왕복 완료, 원격에는 성공적인 수신이 반영됨):

[27314.322482] pIng IN=ens4 OUT= MAC=00:00:17:01:8c:ff:00:00:17:01:cf:b5:08:00 SRC=10.100.21.143 DST=10.100.16.13 LEN= 84 TOS=0x00 PREC=0x00 TTL=64 ID=18269 DF PROTO=ICMP 유형=8 코드=0 ID=14889 SEQ=1 태그=0x2

[27314.323446] pOng IN= OUT=ens4 SRC=10.100.16.13 DST=10.100.21.143 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=39688 PROTO=ICMP TYPE=0 CODE=0 ID=14889 SEQ=1 MARK =0x2

포트 22에 소켓 연결을 시도할 때 유사한 기록된 메타데이터(원격 fwmark가 손실되고 라우팅 테이블이 이를 잘못된 인터페이스로 보내려고 하기 때문에 원격에서 연결이 실패했다고 보고함):

[23305.165235] ens4-PRERT IN=엔스 4OUT= MAC=00:00:17:01:8c:ff:00:00:17:23:a9:ae:08:00 SRC=156.151.8.14 DST=10.100.16.13 LEN=60 TOS=0x10 PREC=0x20 TTL=41 ID=45069 DF PROTO=TCP SPT=5874 DPT=22 WINDOW=14600 RES=0x00 SYN URGP=0 MARK=0x2

[23305.169993] 출력 IN= OUT=엔스 3SRC=10.100.16.13 DST=156.151.8.14 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=22 DPT=5874 WINDOW=26844 RES=0x00 ACK SYN URGP=0

이 게시물이 길어져서 죄송합니다. 나는 이 문제에 대해 한동안 고민해 왔으며 모든 관련 세부 사항을 전달하는 이보다 더 간결한 방법을 생각할 수 없습니다. 비록 "불가능"하더라도 누구든지 제공할 수 있는 지침에 대해 많은 감사를 드립니다. 건배!

답변1

내 의견에 따르면 이것이 예상대로 작동하는 솔루션이라고 생각합니다. 예제와 순서가 반대라는 점에 유의하세요.넷필터 코맥그러나 나가는 패킷이 아닌 들어오는 패킷을 기준으로 결정이 내려지므로 이것이 올바른 순서입니다. 따라서 이전 두 개의 MARK 규칙을 삭제하고(여기에 다시 넣었습니다) 다음으로 바꿉니다.

# iptables -t mangle -A INPUT -i ens3 -j MARK --set-mark 1
# iptables -t mangle -A INPUT -i ens4 -j MARK --set-mark 2    
# iptables -t mangle -A INPUT -j CONNMARK --save-mark

# iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark

대칭성과 명확성을 위해 INPUT(PREROUTING 이후에 호출되지만 로컬 스트림에만 해당)을 사용합니다. 이는 전달이 아닌 로컬 연결용입니다. INPUT 대신 PREROUTING을 사용하면(OUTPUT은 유지) 동일한 결과를 얻을 수 있습니다.

이는 모든 흐름을 추적하는 conntrack을 사용하여 태그를 기억하고 이를 로컬로 생성된 나가는 패킷에 다시 넣습니다. 왜냐하면 conntrack은 태그가 동일한 흐름의 일부임을 알고 있기 때문입니다.

맹글 테이블에서 OUTPUT 규칙을 사용하면 경로 재지정 검사가 시작됩니다(이 내용 참조).Linux 라우팅 및 netfilter 회로도), 이것이 표시에 따라 추적을 라우팅하는 데 필요한 것입니다.

다른 규칙을 사용하거나 -t mangle서버도 전달하는 경우 규칙을 변경해야 합니다. 그럼에도 불구하고 아마도 INPUT에서는 마지막에 있어야 하고 OUTPUT에서는 첫 번째여야 --save-mark합니다 .--restore-mark

이 플래그는 사용자가 아닌 응답 패킷(예: TCP RST)에도 설정되므로 fwmark_reflect더 이상 필요하지 않거나 간섭할 수 있으므로 테스트해야 합니다.

관련 정보