V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
0o0O0o0O0o
V2EX  ›  Linux

Wireguard 与端口转发

  •  
  •   0o0O0o0O0o · 2022-04-27 11:30:06 +08:00 · 7436 次点击
    这是一个创建于 701 天前的主题,其中的信息可能已经有所发展或是发生改变。

    eth0 为服务器的公网网卡,假设 IP 为 1.2.3.4 。

    一直以来我对于 wireguard 的用法都是如下这样的:

    # 服务器
    [Interface]
    Address = 10.0.0.1/32
    ListenPort = 10000
    PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
    PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
    
    [Peer]
    AllowedIPs = 10.0.0.0/24
    
    # 客户端
    [Interface]
    Address = 10.0.0.2/32
    Table = 1
    
    [Peer]
    AllowedIPs = 10.0.0.0/24, 0.0.0.0/0
    Endpoint = 1.2.3.4:10000
    

    这样可以实现客户端通过 wireguard 对外请求:

    curl --interface wg0 https://ifconfig.me
    

    现在想要在维持当前功能的前提下,只通过在服务器修改,实现将服务器的 8888 端口通过 wireguard 转发到客户端上,并且在客户端看来,来源 IP 为 wireguard Endpoint 的 IP ,也就是 10.0.0.1

    按照搜到的常用的 iptables 转发端口的办法可以转发,但是客户端看到的源 IP 是 1.2.3.4

    iptables -t nat -A PREROUTING -p tcp -m tcp -d 1.2.3.4 --dport 8888 -j DNAT --to-destination 10.0.0.2:8888
    iptables -t nat -A POSTROUTING -p tcp -m tcp -d 10.0.0.2 --dport 8888 -j SNAT --to-source 1.2.3.4
    iptables -t nat -A PREROUTING -p udp -m udp -d 1.2.3.4 --dport 8888 -j DNAT --to-destination 10.0.0.2:8888
    iptables -t nat -A POSTROUTING -p udp -m udp -d 10.0.0.2 --dport 8888 -j SNAT --to-source 1.2.3.4
    

    对 NAT 的了解非常模糊...希望能结合这个例子讲解一下,谢谢!

    第 1 条附言  ·  2022-04-27 13:56:46 +08:00

    还有一个前提是客户端的 wireguard 不修改主路由表,即 Table = offTable = 1

    # 客户端
    
    wg-quick up wg0
    
    # 监听 TCP
    nc -vlk 8888
    
    # 监听 UDP
    nc -vlu 8888
    

    在以上这些条件下,server 只有将 --to-source 改为 server 的 eth0 IP,TCP 才可以正常。虽然可以通信,但是 client 无法获取源 IP 信息;

    而这种条件下的 UDP,我觉得理论上 client 需要拿到源IP,并 bind device 才可以发送,就不知道该如何处理了。

    第 2 条附言  ·  2022-04-27 14:19:43 +08:00
    UDP 应该是解决了,验证了下,把第四条 iptables 删掉就可以保持源 IP ,然后 client 侧 bind device 之后直接发 UDP 即可。

    但 TCP 的源 IP 在不改变 client 的主路由表的前提下想不到什么办法来解决。
    18 条回复    2022-04-28 09:50:13 +08:00
    DianQK
        1
    DianQK  
       2022-04-27 12:45:07 +08:00   ❤️ 1
    似乎没办法实现?客户端上看到源 IP 为 1.2.3.4 时,这个是 WireGuard 协议的包,如果通过 SNAT (好像是这个吧?)改成 10.0.0.1 ,那下一步客户端应该会把 WireGuard 协议的包发到 10.0.0.1 ?
    (不知道我想的对不对
    tavimori
        2
    tavimori  
       2022-04-27 13:22:42 +08:00
    把 SNAT 部分的 IP 改成 10.0.0.1 应该就可以?

    ```
    iptables -t nat -A PREROUTING -p tcp -m tcp -d 1.2.3.4 --dport 8888 -j DNAT --to-destination 10.0.0.2:8888
    iptables -t nat -A POSTROUTING -p tcp -m tcp -d 10.0.0.2 --dport 8888 -j SNAT --to-source 10.0.0.1
    iptables -t nat -A PREROUTING -p udp -m udp -d 1.2.3.4 --dport 8888 -j DNAT --to-destination 10.0.0.2:8888
    iptables -t nat -A POSTROUTING -p udp -m udp -d 10.0.0.2 --dport 8888 -j SNAT --to-source 10.0.0.1
    ```
    wd
        3
    wd  
       2022-04-27 13:29:57 +08:00 via iPhone   ❤️ 1
    你的那个 snat 就是决定客户端看到的 ip ,你设置的不就是 1.2.3.4 吗?你改成 10.0.0.1 看看
    0o0O0o0O0o
        4
    0o0O0o0O0o  
    OP
       2022-04-27 13:34:09 +08:00
    @tavimori #2
    @wd #3

    如#1 所说,这样的话 TCP 不通,而 UDP 是能收到的,但 UDP 只要用 SNAT 改变了源 IP ,客户端收到后就不知道该往哪发了
    0o0O0o0O0o
        5
    0o0O0o0O0o  
    OP
       2022-04-27 13:36:38 +08:00
    @0o0O0o0O0o #4 抱歉试错命令了。。。TCP 是通的,UDP 不知道如何解决
    wd
        6
    wd  
       2022-04-27 13:38:31 +08:00 via iPhone
    @0o0O0o0O0o 1 楼说的是啥有点没明白。这么问吧,你在 client 的 8888 的服务,在服务器上能访问通吗?
    0o0O0o0O0o
        7
    0o0O0o0O0o  
    OP
       2022-04-27 13:57:37 +08:00
    @wd #6 可以访问,我添加了附言
    0o0O0o0O0o
        8
    0o0O0o0O0o  
    OP
       2022-04-27 13:58:04 +08:00
    @0o0O0o0O0o #5 在 client 修改主路由表的前提下才通,不修改主路由表是不通的
    tavimori
        9
    tavimori  
       2022-04-27 14:27:58 +08:00   ❤️ 1
    如果 Table = off 的话 wg-quick 并不会自动配置回程路由,即客户端不会将目标为 10.0.0.1 的包路由通过 wireguard 传回服务器。

    三种修改建议(任选其一即可):
    1. 将客户端 Address 字段前缀改为 /24 即:
    Address = 10.0.0.2/24

    2. 在客户端增加 post up 脚本设置 10.0.0.0/24 走 wireguard 路由

    3. 如果 wg 只需要支持这一个应用,在服务端使用 NAT 后,客户端 AllowedIPs 里可以去掉 0.0.0.0/0 , 并启用 Table = auto ,这样只会建立 10.0.0.0/24 的路由。
    0o0O0o0O0o
        10
    0o0O0o0O0o  
    OP
       2022-04-27 14:54:22 +08:00
    @tavimori #9 感谢耐心解答。

    将客户端 Address 字段前缀改为 10.0.0.2/24 就可以解决 tcp 通过 SNAT 修改 --to-source 为 10.101.0.1 的问题。

    ip route 查看,相比之前它添加了一条 `10.101.0.0/24 dev wg0 proto kernel scope link src 10.101.0.2`。
    webfrogs
        11
    webfrogs  
       2022-04-27 14:58:58 +08:00   ❤️ 1
    只 DNAT 不就好了么? 因为做了 SNAT 才导致 client 看到的 IP 是 1.2.3.4
    0o0O0o0O0o
        12
    0o0O0o0O0o  
    OP
       2022-04-27 15:07:12 +08:00
    @tavimori 如果希望依然不修改客户端主路由表( Table = off ),但又希望可以在客户端拿到 TCP 的源 IP ,有办法实现吗...
    0o0O0o0O0o
        13
    0o0O0o0O0o  
    OP
       2022-04-27 15:19:31 +08:00
    @0o0O0o0O0o #12 源 IP 可以认为是 0.0.0.0/0
    tavimori
        14
    tavimori  
       2022-04-27 16:00:26 +08:00
    @0o0O0o0O0o
    如果客户端收到的 TCP 请求是来自源 IP (我理解你说的源 IP 应该是 1.2.3.4 ?)的话,那么就必须确保客户端将发回该源 IP 的数据包路由经过 wireguard 。如果你想避免将 wireguard 配置成默认路由( Table = off ),那么就必须针对性的添加路由。
    (以下假设 linux )例如在客户端的[Interface]下增加以下内容
    PostUp = ip route add 1.2.3.4/32 dev %i
    PreDown = ip route delete 1.2.3.4/32 dev %i
    0o0O0o0O0o
        15
    0o0O0o0O0o  
    OP
       2022-04-27 16:09:25 +08:00 via iPhone
    @tavimori #14 我可能用词不当,应该说是服务端的 8888 端口收到的 TCP 连接的 remote address ,而不是服务端的公网 IP ,是未知的,可以假设为 0.0.0.0/0
    tavimori
        16
    tavimori  
       2022-04-27 16:47:12 +08:00   ❤️ 1
    @0o0O0o0O0o
    建议在客户端配置基于源地址的策略路由。即源地址为 10.0.0.2/32 的走 wg ,源地址为其他地址 ip 的走系统原来的默认路由。

    (以下假设 linux )例如在客户端的[Interface]下增加以下内容:

    PostUp = ip route add default dev %i table 10086 src 10.0.0.2
    PostUp = ip rule add from 10.0.0.2 table 10086
    PreDown = ip rule delete from 10.0.0.2 table 10086
    PreDown = ip route delete default dev %i table 10086 src 10.0.0.2
    zbinlin
        17
    zbinlin  
       2022-04-27 20:25:36 +08:00
    如果是 http 服务的,直接用 nginx 来做反代是最简单的
    orannge
        18
    orannge  
       2022-04-28 09:50:13 +08:00
    要么 dnat+snat ,不影响当前网络,但多了一层 nat ,有连接数和保持时间的问题。要么 dnat+0.0.0.0/0 ,保留原始 ip ,但除了局域网其它流量都走 wg ,如果主机不想这样可以将 wg 和程序一起放 docker 运行。至于 iptables 必定要改的,无非手动还是自动的区别,因此用默认的`Table = auto`即可。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3157 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 12:34 · PVG 20:34 · LAX 05:34 · JFK 08:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.