V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
lsylsy2
V2EX  ›  问与答

求问关于 iptables 端口映射的问题,求对网络比较熟的人帮忙

  •  
  •   lsylsy2 · 2014-08-22 17:04:05 +08:00 · 3350 次点击
    这是一个创建于 3546 天前的主题,其中的信息可能已经有所发展或是发生改变。
    目标:想要在公网做端口映射,用iptables实现,功能有些类似“haproxy的TCP转发”。
    网络环境:(IP替换过)
    服务器A:Azure,公网IP 8.8.8.1,内网IP 10.8.8.1;
    服务器B:某VPS,网卡直接绑定公网IP 8.8.8.2;
    在AB之间利用openvpn建立了隧道,Azure端IP 10.0.0.1,VPS端IP 10.0.0.2,测试通过这对IP ping wget均正常。
    目标:访问http://8.8.8.1/,请求能够被发送到服务器B

    目前iptables用的是这两条规则:
    -A PREROUTING -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.2
    -A POSTROUTING -o eth0 -j MASQUERADE

    从我的个人电脑(IP 8.8.8.3)进行了telnet 8.8.8.1 80
    并且tcpdump抓包测试,结果如下:
    1、服务器A上,8.8.8.3->10.8.8.1 SYN包,这是正常的外网连接Azure;
    2、服务器A上,8.8.8.3->10.0.0.2 SYN包,这是第一个包经过iptables转换,目标地址变成了服务器B;
    3、服务器B上,8.8.8.3->10.0.0.2 SYN包,这个SYN包被成功的发送了过来;
    4、服务器B上,10.0.0.2->8.8.8.3 SYN-ACK包,进行TCP三步握手;

    然后包4就丢失了……至少看起来是丢失了,#服务器A并没有收到这个ACK#,后面有几个重发的SYN与SYN-ACK包,但是都是1234中的某一个。求问这是哪里设置的问题么?
    第 1 条附言  ·  2014-08-22 20:16:57 +08:00
    我现在有一点疑惑:
    在ifconfig里面,公网的那个IP和VPN的IP各占一个网卡,他们的地位应该是完全相同的;
    如果这种情况下无法建立链接的话,那么那些有着多个网卡、多个IP地址的服务器,难道一个用户就只能访问一个IP,其它IP都链接不通么?难道不应该是默认哪里来哪里去么?
    第 2 条附言  ·  2014-08-24 02:40:46 +08:00
    成功了!测试了可以通过服务器A的2222端口连接服务器B的SSH(通过2222转发到22),然后服务器B上netstat能获取我客户端的IP。
    最后服务器B修改iptables无效,而是用iprouter2解决的,具体的我明天睡醒了再整理写博客,大家可以期待一下ww
    11 条回复    2014-08-24 02:36:46 +08:00
    tmqhliu
        1
    tmqhliu  
       2014-08-22 19:37:13 +08:00
    建议你直接用 nginx 之类的反向代理就行,应用层的需求可以用应用层的方式来解决,不要什么都想着用 iptables

    如果你用 DNAT 把包交给 Server B ,Server B 在返回时也要有相应的路由。不能只有去的路,没有回来的路。
    lsylsy2
        2
    lsylsy2  
    OP
       2014-08-22 19:50:17 +08:00
    @tmqhliu 现在的问题就是应用层直接读取的TCP对方IP,闭源软件无法修改……
    回来和去走一条路不行么?假如我的电脑插了两根网线,分别是电信联通,难道有一边无法使用么?
    tmqhliu
        3
    tmqhliu  
       2014-08-22 20:12:18 +08:00
    如果软件读 8.8.8.1 ,你在8.8.8.1 上配置一个 http透明代理,把请求转交给实际的服务器B不行么?


    你没理解我的话。走一条路当然可以,但这事需要配置,并不是你一厢情愿就可以的
    lsylsy2
        4
    lsylsy2  
    OP
       2014-08-22 20:15:12 +08:00
    @tmqhliu 走的并不是HTTP协议,是一个裸的TCP协议,内部内容我无法修改,直接TCP转发会导致无法获取用户IP从而影响功能
    我的问题是,像“站群VPS”那样,一台Linux上绑着很多个IP,那么一个用户只能访问一个IP上的网站么?
    tmqhliu
        5
    tmqhliu  
       2014-08-22 20:27:31 +08:00
    哦 原来是原生 TCP 那就没法搞代理了

    站群那样配了很多个 IP,但可能只有一个网关,返回的数据包下一跳就是这个网关地址。而你的服务器B,是在两个接口上配了两个不同的ip,如果数据包是从 tun 接口进来的,返回的包却从 eth 公网接口出去,很可能是目的地址不可达(没有相应的路由)所以就收不到返回的数据包了,自然 TCP 连接也无从谈起。

    建议你在 服务器 B 上 traceroute 一下客户端的 IP (比如主贴中你的pc地址)看一下是否是畅通的。
    tmqhliu
        6
    tmqhliu  
       2014-08-22 21:11:04 +08:00
    “难道不应该是默认哪里来哪里去么?” 这个还真不是,你看看 2006 年就有人提这个问题了:
    《多线路服务器如何让访问数据包从哪条线路进就从哪条出》
    http://www.linuxsir.org/bbs/thread277992.html

    你的问题是,数据包是在服务器 A 上由 iptables 经 DNAT 之后通过 VPN 隧道发给服务器 B,服务器 B 在收到连接请求后,发送 SYN+ACK,但是从公网接口发送出去的。公网上的路由器在收到一个源地址为 10 开头的包,很可能就会扔掉了,因为这种私有地址的包不应该出现在公网上。
    tmqhliu
        7
    tmqhliu  
       2014-08-22 21:13:06 +08:00   ❤️ 1
    解决方案: 在服务器B上添加策略路由,指定源地址为 10.0.0.2 的包从接口 tun 发出去。
    lsylsy2
        8
    lsylsy2  
    OP
       2014-08-22 21:34:39 +08:00
    @tmqhliu 十分感谢!
    jerry74
        9
    jerry74  
       2014-08-22 22:38:14 +08:00
    试试看吧
    iptables -t nat -I PREROUTING -d 8.8.8.1 -p tcp -m tcp --dport 80 -j DNAT --to-destination 8.8.8.2
    lsylsy2
        10
    lsylsy2  
    OP
       2014-08-23 00:17:27 +08:00
    -A PREROUTING -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.2
    @jerry74 我现在用的是这个,没有问题的;
    你想说公网是么,那个不好使……
    lsylsy2
        11
    lsylsy2  
    OP
       2014-08-24 02:36:46 +08:00
    @jerry74
    @tmqhliu
    成功了!测试了可以通过服务器A的2222端口连接服务器B的SSH(通过2222转发到22),然后服务器B上netstat能获取我客户端的IP。
    最后服务器B修改iptables无效,而是用iprouter2解决的,具体的我明天睡醒了再整理写博客好了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3141 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 15:16 · PVG 23:16 · LAX 08:16 · JFK 11:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.