一个 iptables 做 SNAT 的问题

2021-10-13 23:03:15 +08:00
 s82kd92l
linux iptables 里的 SNAT 好像只有 SYN 包会进过 nat 表的逻辑,后面的包都自动根据 conntrack 做 SNAT.

现在有个小众的需求:程序在端口 A listen + accept, 但我希望用 iptables 把所有的回复包的 src port 都从 A 改为 B. 但由于这个程序只会发送 SYNACK, 不发送 SYN , 普通的 iptables nat 规则就做不到

各位大神有什么想法吗?
2485 次点击
所在节点    Linux
7 条回复
rrfeng
2021-10-13 23:04:27 +08:00
这不是 dnat
s82kd92l
2021-10-13 23:10:01 +08:00
@rrfeng 不是想做 DNAT. 我是想把原来的 tcp 一拆为 2.

比如客户端端口是 S , 发送包到服务器端口 D1, 服务器用 D2 回复客户端, 客户端再想办法在内核把 D2 变回 D1 。这样在外网看来上下行就是两条完全独立的半连接。
24owls
2021-10-13 23:30:40 +08:00
> 比如客户端端口是 S , 发送包到服务器端口 D1, 服务器用 D2 回复客户端, 客户端再想办法在内核把 D2 变回 D1 。这样在外网看来上下行就是两条完全独立的半连接。

这样就不能用内核的 TCP 了吧,那就用 raw socket 自己实现你这个自定义协议呗
s82kd92l
2021-10-13 23:41:23 +08:00
@24owls 对于发出去的包,tcp stack 处理完了才轮到 iptables 这个逻辑不影响 tcp stack 正常工作吧
24owls
2021-10-14 00:28:17 +08:00
刚刚读了一遍 nft(8), 你这个看起来可以用 nft notrack 解决

nft 规则: 127.0.1.1:1234 -> 127.0.1.2:4321

# nft -f- <<EOF
table inet raw {
chain prerouting {
type filter hook prerouting priority raw; policy accept;
ip daddr 127.0.1.1 tcp dport 1234 notrack ip daddr set 127.0.1.2 tcp dport set 4321 log prefix "RAW "
ip saddr 127.0.1.2 tcp sport 4321 notrack ip saddr set 127.0.1.1 tcp sport set 1234 log prefix "RAW "
}
}
EOF

测试结果

# echo 4321 out | nc -l 127.0.1.2 4321 &
# echo to 1234 | nc 127.0.1.1 1234
4321 out
to 1234
[1] + Done echo 4321 out | nc -l 127.0.1.2 4321

log 记录

# journalctl --priority=warning..warning --no-hostname | grep RAW
Oct 14 00:22:47 kernel: RAW IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.1.1 DST=127.0.0.1 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=1234 DPT=41882 WINDOW=65483 RES=0x00 ACK SYN URGP=0
Oct 14 00:22:47 kernel: RAW IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.0.1 DST=127.0.1.2 LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=49359 DF PROTO=TCP SPT=41882 DPT=4321 WINDOW=512 RES=0x00 ACK URGP=0
Oct 14 00:22:47 kernel: RAW IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.0.1 DST=127.0.1.2 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=49360 DF PROTO=TCP SPT=41882 DPT=4321 WINDOW=512 RES=0x00 ACK PSH URGP=0
Oct 14 00:22:47 kernel: RAW IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.1.1 DST=127.0.0.1 LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=30729 DF PROTO=TCP SPT=1234 DPT=41882 WINDOW=512 RES=0x00 ACK URGP=0
Oct 14 00:22:47 kernel: RAW IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.0.1 DST=127.0.1.2 LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=49361 DF PROTO=TCP SPT=41882 DPT=4321 WINDOW=512 RES=0x00 ACK FIN URGP=0
Oct 14 00:22:47 kernel: RAW IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.1.1 DST=127.0.0.1 LEN=61 TOS=0x00 PREC=0x00 TTL=64 ID=30730 DF PROTO=TCP SPT=1234 DPT=41882 WINDOW=512 RES=0x00 ACK PSH URGP=0
Oct 14 00:22:47 kernel: RAW IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.0.1 DST=127.0.1.2 LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=49362 DF PROTO=TCP SPT=41882 DPT=4321 WINDOW=512 RES=0x00 ACK URGP=0
Oct 14 00:22:47 kernel: RAW IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.1.1 DST=127.0.0.1 LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=30731 DF PROTO=TCP SPT=1234 DPT=41882 WINDOW=512 RES=0x00 ACK FIN URGP=0
Oct 14 00:22:47 kernel: RAW IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.0.1 DST=127.0.1.2 LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=49363 DF PROTO=TCP SPT=41882 DPT=4321 WINDOW=512 RES=0x00 ACK URGP=0
24owls
2021-10-14 00:37:15 +08:00
查了一下 stackexchange 上面也有答案 https://unix.stackexchange.com/a/429551
s82kd92l
2021-10-14 14:07:33 +08:00
@24owls 多谢, 我试试

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/807668

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX