有偿找懂路由 iptables tcp udp 的老哥解决一个全端口转发的问题

253 天前
 AaIT

机器 A:1.1.1.1
机器 B:2.2.2.2

二台都是具有独立公网 IP 的 KVM 虚拟机
公网 IP 都是静态配置在虚拟机内部也就是经典网络

A 只允许 B 的 IP 入站,其他 IP 全部屏蔽流量进不来
这样就导致远程管理 ssh 也进不去了,所以需要 B 把流量转发到 A 上

B 的 IP 完全为 A 提供服务,希望能实现访问 B 的任意端口就等于访问 A 的对应端口
需要能转发 TCP 和 UDP 流量,当然 TCP 这个简单些,UDP 这个就比较麻烦了

A 交付给客户,所以方案尽量不用在 A 的机器上安装什么东西
B 客户用不了,只是作为透明转发

方案还是有很多,比如可以组 IP 隧道然后路由到隧道里
或者直接 A 做内网穿透客户端 B 做内网穿透服务器端
但这些都需要在 A 上安装程序做对接

IP 路由的话好像改不了源 IP 这样压根过不了 A 的防火墙
目前尝试 iptables 端口段转发性能不是太好,另外 UDP 能通但无法传输数据

有经验的老哥请加我微信,谢谢

2519 次点击
所在节点    程序员
31 条回复
iqoo
253 天前
写个 libpcap 程序转发包会不会更简单些~
yyzh
253 天前
你是不是在说 1:1NAT?
zbinlin
253 天前
全部端口都转发了,这样做对于 A 的入站限制不是没意义了?
AaIT
253 天前
@zbinlin 有意义呀,入站限制不是为了保护流量,而是为了保护 A 的 IP 防止外部探测
360750581
252 天前
那这么做了,探测 B 不就是探测 A ?
zbinlin
252 天前
怎么测试的?如果转发可以试试走 OFFLOAD
kaedeair
252 天前
绑个域名 tcp 反代的事
wangbin526
252 天前
没理解,既然 A 的防火墙只允许 B 的 IP 入站,B 的 IP 对外泄露需要更换的话,还得手动修改 A 的防火墙配置啊
至于配置转发的话,手动配置 IP-Tables 容易出错,建议通过 UFW 的 IP 伪装功能来配置,透明转发或者指定端口转发都行,没接触过这么奇怪的需求,理论上应该可行吧
开个玩笑,如果 B 单纯做透明转发的话,干脆 B 装个 OpenWrt ,然后将 A 的 IP 设置为 DMZ 主机,完全映射端口不就是了
kuanat
252 天前
直接说结论:如果 A 的防火墙
kuanat
252 天前
直接说结论:

如果 A 的防火墙是类似于 `iptables -t nat -A PREROUTING -s 2.2.2.2 -j ACCEPT` 的形式,那就无法通过 NAT 的形式做端口映射。

做全端口映射的原理就是楼上说的 DMZ ,转换成 iptables 规则就是 B 作为 A 的网关,对出流量做 SNAT ,对入流量做 DNAT 。

但是 A 的防火墙规则限制了来源只能是 B ,那 B 要对入流量同时做 SNAT ,修改其来源 IP 为 B 2.2.2.2 ,这就导致 A 认为请求来源都是 B ,回复的 DstIP 都是 B 2.2.2.2 ,因而无法正常返回数据。

解决的办法是:

1. B 以反向代理( reverse proxy )的形式工作,这样 A 可以保留防火墙规则。但反向代理对于协议有限制,tcp/http 类可以,udp 很难。

2. A/B 各自增加一个网络接口,两个接口之间建立某种点对点链路,然后走 NAT 映射
pedh
252 天前
A 只允许 B 的 IP 入站,这个是有状态还是无状态的?或者说 A 主动访问公网,你希望源 ip 是 1.1.1.1 还是 2.2.2.2 ?
AaIT
252 天前
@kuanat #10 感谢细致回复,这里补充下信息,

A 是交付给客户使用的虚拟机,大多数是 Linux 也有部分客户装 win 系统
所以最好 A 机器不要装任何东西和做任何调整,所有的操作在 B 机器完成

二台机器都在美国同一个城市,不涉及跨境也没有网络抖动
A 机器内部没有防火墙,限制是在安全组上做的,类似阿里云服务器的安全组

这么做的原因是 A 是住宅 IP 所以不想对外暴露任何端口,并不是为了保护流量或者别的啥
仅仅是为了保护 A 的 IP 本身,且由于封闭了入站造成管理和远程使用的麻烦

就想着用另一个机房 IP 也就是 B 来转发所有流量,虽然屏蔽了入站随便弄个 tailscale 组网非常简单
但对用户来说不简单,或者内网穿透也可以,所以最终的目的就是 A 屏蔽入站的前提下不改变使用习惯

只要日常使用连接 B 就等于连接 A 透传所有的流量过去,比如 socks5 这种,不仅仅是 TCP 直播还需要用到 UDP 协议

处理起来都很麻烦,所以感觉有点棘手
AaIT
252 天前
@wangbin526 是为了保护 A 得住宅 IP 哈,B 得 IP 泄露无所谓的,B 是一个机房的 IP ,随便泄露没啥事
kuanat
252 天前
因为你这个做法很不常见,我猜测可能是 XY 问题导致的偏差,所以特地去看了你的使用场景。

这里我引用一下"为什么要搞 IP 保护"的描述:"暴露的端口会被探测",看到这里我就理解你的需求了。

本质上你是在保护自己的 IP 资产,而不是客户,客户只是租用而已。因为你以虚拟机的形式为客户交付服务,并不能控制客户在虚拟机上的行为,比如客户可以在在这个公网 IP 上开放公开的 http/socks 服务等等。

怎么向客户描述这个问题不重要,但是你的思路被带偏了,甚至说你的整体产品架构思路都被带偏了。当然这只是我个人的想法,可能理解有偏差。

如果我来设计的话,向客户交付的部分其实是 B ,而 A 是由自己完全控制的,A 是 B 的路由器。技术层面,B 本身就是云服务,利用 VPC 保证 B 的所有出站流量都一定由 A 路由就可以了。

这样做的附加好处是,所有 A 节点都可以用低成本标准化的网络设备完成,无需托管真实主机,至于 B 完全可以利用云服务来提供定制。
tril
252 天前
单端口转发我是这么做的,UDP 也可以正常转发。不知道多端口转发可不可以靠复制 65535 遍或者将单端口换成端口段( 443 改成 1:65535 )或者直接删除端口相关参数来实现,仅供参考。

假设 2.2.2.2 是你 B 机入站网卡上获得的 IP ( B 机的公网 IP 是多少不重要),将 B 的 443/udp 端口转发到 A 的 443/udp 端口:

# 目的地转换
iptables -t nat -A PREROUTING -p udp -d 2.2.2.2 --dport 443 -j DNAT --to-destination 1.1.1.1:443
# 源地址转换
iptables -t nat -A POSTROUTING -p udp -d 1.1.1.1 --dport 443 -j SNAT --to-source 2.2.2.2

# 如果 B 机启用了 UFW 则需要放行对应的转发流量
# ufw route allow to 1.1.1.1 port 443 proto udp
# 内核需要允许 IPv4 转发
# echo 'net.ipv4.ip_forward=1' > /etc/sysctl.conf && sysctl --system

数据进 B 的时候先做目的地转换,改成“客户端-->A”,在数据出 B 之前做源地址转换,进一步改成“B-->A”。回程的时候 B 机会自动反向操作一遍,最终发给客户端的数据是“B-->客户端”。

TCP 同理,只需要把 udp 改成 tcp 。
realpg
252 天前
你这个涉及逻辑都不自洽

如果按照你的设想,任何 tcp udp 包到 B 的 ·任意· 端口都转发给 A 那么 B 就相当于跟互联网断开了……
AaIT
252 天前
@kuanat #14 是的,是这个道理,老哥理解很到位,只是目前刚起步小规模不想把架构弄的太复杂
就是能用稳定就行,有位 V 站老哥详细帮我查了,后来发现并不是 NAT 转发性能不行
而是 ATT 宽带的光猫不行对数据包有限制,每秒 25pps ICMP TCP UDP 都这样
但是走隧道的话好像不会触发限制,这样集中转发,源 IP 都是 B 更容易触发限制
大概情况情况就是这样,看来只能双向建立隧道,然后走隧道通讯了


AaIT
252 天前
@realpg 是的,这是作为小白的一种直白的表达,不用深究技术细节
feather12315
252 天前
要性能用 xdp ,cllium 项目。
具体怎么用需要看看。
1423
252 天前
原来你就是博客里喷 AperNet 的那个..

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

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

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

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

© 2021 V2EX