使用 nginx 实现端口流量转发,需求是 ip 透传,请教下我该如何实现? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Raul7
V2EX    NGINX

使用 nginx 实现端口流量转发,需求是 ip 透传,请教下我该如何实现?

  •  
  •   Raul7 2020-06-11 18:40:09 +08:00 8397 次点击
    这是一个创建于 1996 天前的主题,其中的信息可能已经有所发展或是发生改变。

    客户端( Client ):A 机器

    Nginx 机器:B 机器

    转发的目标:C 机器

    需求:A 机器请求 B 机器的端口,将 B 机器的端口( TCP/UDP )流量转发到 C 机器。C 机器记录到的请求 ip 要是 A 机器的 ip 。


    网上查询到这篇文章: https://cloud.tencent.com/developer/article/1449427

    文章中列了三种方案,分别是 IP 地址透传、DSR (上游服务无公网)、DSR (上游服务有公网)。

    方案 1 和方案 2 适配我当前的环境,但是需要 C 机器配置网关,但是目前的环境限制,不允许我修改 C 机器的网关(主要是修改网关可能会影响 C 机器上跑的服务)。

    请教下 V 友们,我的需求该如何实现呢?

    第 1 条附言    2020-06-12 00:30:10 +08:00
    抱歉 问题没说清楚 HTTP 协议的话是很简单,我的需求是 TCP/UDP 协议。
    42 条回复    2021-05-27 16:08:33 +08:00
    tomczhen
        1
    tomczhen  
       2020-06-11 19:59:54 +08:00 via Android   3
    要么是 xy 问题,要么你应该去看看 TCP/IP 协议相关的知识,至少先了解下 IP 协议再说。

    其他人就别浪费时间了。
    joesonw
        2
    joesonw  
       2020-06-11 20:05:02 +08:00
    你需要的是 iptables
    xl224
        3
    xl224  
       2020-06-11 20:05:45 +08:00 via iPhone
    nginx 配置转发时增加 X-Real-IP HTTP 头,到了 C 里面通过过去 http 头拿到真实 ip
    dreamage
        4
    dreamage  
       2020-06-11 20:19:05 +08:00
    x-forward-for
    proxy protocol
    tcp option
    SaberJack
        5
    SaberJack  
       2020-06-11 20:20:31 +08:00 via Android
    今天刚遇到这个问题:nginx 通过 X-Forwarded-For 获得用户的真实 ip,就必须先使用 proxy_set_header X-Forwarded-For $roxy_add_x_forwarded_for 。
    hundan
        6
    hundan  
       2020-06-11 20:41:05 +08:00 via iPhone
    简单说一下

    这篇文章说的是四层下 tcp 和 udp 的 ip 透传问题 所以你的需求是 http 还是 tcp/udp ?

    3-5 楼说的都是 http 协议 2 楼说的没有涉及到透传问题

    如果是 http 协议 加一个 x-forward-for 就可以了

    如果不是 ...
    hundan
        7
    hundan  
       2020-06-11 20:42:19 +08:00 via iPhone
    仔细看了一下帖子 的确不是 http 协议哈 有答案了记得艾特我一下 学习学习
    myd
        8
    myd  
       2020-06-11 20:47:32 +08:00 via Android
    端口转发,用 ssh 就可以实现
    also24
        9
    also24  
       2020-06-11 20:47:48 +08:00
    首先需要确认一下你需要转发的流量类型,如果只是 http 协议的流量,那么可以使用 HTTP X-Forwarded-For 解决。

    但是如果你需要转发的是纯 TCP / UDP 流量的话,就需要使用 Proxy Protocol 了。
    遗憾的是,nginx 只支持对 TCP 流量转发启用 Proxy Protocol 功能。

    如果希望对 UDP 流量也生效,就需要一些魔改方案了。
    我看到一篇文章对更魔改的方案做了介绍,可以看一下:
    http://www.taohui.pub/2018/04/08/udp%E7%9A%84%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%EF%BC%9Anginx/
    also24
        10
    also24  
       2020-06-11 20:52:21 +08:00
    噗嗤,我看了下楼主给的链接,原来是同一篇文章 hhh
    also24
        11
    also24  
       2020-06-11 21:00:14 +08:00
    继续补充一下,其实我个人对方案 2 方案 3 很不喜欢,觉得已经属于魔改的范畴。

    为什么要吊死在 nginx 上呢?也许可以尝试下 traefik 看看?

    从文档上来看,traefik 似乎是同时支持 UDP 和 Proxy Protocol 的。
    https://docs.traefik.io/routing/entrypoints/#proxyprotocol
    also24
        12
    also24  
       2020-06-11 21:09:44 +08:00
    另:
    我本来还是对 haproxy 抱有希望的,翻了下发现,他们好像并不打算支持 UDP
    https://github.com/haproxy/haproxy/issues/62
    Raul7
        13
    Raul7  
    OP
       2020-06-12 00:31:33 +08:00
    @also24 是哈 haproxy 我测试了 不支持 UDP 协议。
    nuk
        14
    nuk  
       2020-06-12 00:55:12 +08:00
    tcp/udp stream 。。。要企业版。。得花钱。。。
    est
        15
    est  
       2020-06-12 01:00:19 +08:00 via Android
    lz 还是去付费咨询吧,优质客户
    aladdindingding
        16
    aladdindingding  
       2020-06-12 09:19:58 +08:00
    proxy protocol 会在数据包头加一层 自己做解析吧
    Raul7
        17
    Raul7  
    OP
       2020-06-12 09:21:45 +08:00
    @aladdindingding 目前 nginx 对 proxy protocol 的支持则仅止于 tcp 协议,还不支持 udp 协议-^-
    dowson521
        18
    dowson521  
       2020-06-12 09:34:03 +08:00
    这个问题我也一直在想办法处理,目前没有找到合适的方案。
    方案 1:nginx 转发 tcp/udp 在 proxy_bind 那里增加 transparent 参数 并将配置文件中 user 改为 root 同时要修改路由。据 nginx 官方文档说是可以实现,但是目前看来网络上并没有成功实现的范例。
    proxy_protocol 这个协议头需要代理和被代理的两端都使用支持该协议的转发程序,限制太多了。另外 nginx 企业版也没有这样的功能。

    总之这个问题不太好解决:(
    also24
        19
    also24  
       2020-06-12 10:33:18 +08:00 via Android
    @Raul7
    有没有试试我在 11 楼提到的 traefik
    okletswin
        20
    okletswin  
       2020-06-12 10:39:46 +08:00
    纯 4 层转发,考虑下 lvs ? dr 或者 fullnat 模式
    abcbuzhiming
        21
    abcbuzhiming  
       2020-06-12 11:48:01 +08:00
    Nginx 的开源版曾经是是不支持第 4 层(传输层 TCP/UDP)转发的。商业版有第 4 层转发。

    但是现在有一个 stream 模块支持这个,用 Nginx -V 查看模块,检查是否安装了
    --with-stream
    --with-stream_realip_module

    第一个模块能实现传输层转发,第二模块实现了 PROXY 协议标头( 1.11.4 )中发送请求来源的的地址和端口
    http://nginx.org/en/docs/stream/ngx_stream_realip_module.html
    fengjianxinghun
        22
    fengjianxinghun  
       2020-06-12 13:49:02 +08:00
    你们不知道有 tproxy 可以透传 tcp+udp ?
    mgrddsj
        23
    mgrddsj  
       2020-06-12 13:54:12 +08:00
    tcp/udp 的话应该是用 iptables 吧?
    Meano
        24
    Meano  
       2020-06-12 14:12:50 +08:00
    难道要做协议伪装?为了抗 ISP QOS 做 tcp/udp-over-http 么
    julyclyde
        25
    julyclyde  
       2020-06-12 14:33:04 +08:00
    首先限定了错误的方法和目标要求
    然后问怎么实现
    Raul7
        26
    Raul7  
    OP
       2020-06-12 17:21:28 +08:00
    @julyclyde ???
    Raul7
        27
    Raul7  
    OP
       2020-06-12 17:22:11 +08:00
    @mgrddsj iptables 透传不了 udp
    Raul7
        28
    Raul7  
    OP
       2020-06-12 17:26:49 +08:00
    @fengjianxinghun 请教大佬 tproxy 如何配置呢?
    Raul7
        29
    Raul7  
    OP
       2020-06-12 17:29:52 +08:00
    @also24 我还在研究 网上没找到好的参考资料
    littlewing
        30
    littlewing  
       2020-06-12 17:38:09 +08:00
    你需要 4 层负载均衡,比如说 LVS
    Raul7
        31
    Raul7  
    OP
       2020-06-12 18:06:40 +08:00
    @littlewing 肿么配置呀 有相关的文章吗表哥 我参考一下
    pagxir
        32
    pagxir  
       2020-06-12 18:07:02 +08:00 via Android
    不管你怎么弄,你都得修改路由让 C 到 A 的报文经过 B 机器。不过你只是想知道 A 机器的 IP 而不担心修改 C 的程序,你可以用 IPv6 的 NAT64 。否则你可以在 B 跟 C 之间建立 IPv4 隧道,让 c 到 a 的报文走隧道。
    littlewing
        33
    littlewing  
       2020-06-12 18:09:26 +08:00
    @Raul7 google 一搜一大推,非常成熟的东西了,很多大公司也用
    sujin190
        34
    sujin190  
       2020-06-12 18:17:42 +08:00
    代理的话,能配出 C 直接看到是 A 的 ip,又不在应用层协议内支持,nginx 应用层不可能做到,ip 层应该是可能的,那么你这是要逆天啊

    单纯转发流量的话太简单了,自己做一个都不需要 3 分钟
    warcraft1236
        35
    warcraft1236  
       2020-06-12 18:21:55 +08:00
    nginx 能做 if 判断吗?比如如果是 http 就转发到哪,不是就转发到哪
    Aruforce
        36
    Aruforce  
       2020-06-12 18:46:02 +08:00
    C 机器记录到的请求 ip 要是 A 机器的 ip 。

    这个 NGINX 实现不了吧?
    zgk
        37
    zgk  
       2020-06-12 19:02:17 +08:00
    传输层的 TCP/UDP 协议本质上是基于 IP 协议之上工作的,基于传输层想改请求 IP 的记录并不可能啊?

    假设就算改了来源的报文,B 与 C 在 TCP 握手时往回发送 IP 包也会直接往 A 机器去发了,连接也建立不起来。这里的限制条件已经无法满足了。
    watzds
        38
    watzds  
       2020-06-12 19:21:15 +08:00 via Android
    这个 NAT 实现不了,一般用 LVS 或者 iptables
    kaneg
        39
    kaneg  
       2020-06-12 21:58:11 +08:00 via iPhone
    nginx 做不到的,得用 F5
    vsyour
        40
    vsyour  
       2020-09-17 12:29:11 +08:00
    尝试试了很多办法不行.
    aaa998
        41
    aaa998  
       2020-10-27 16:27:33 +08:00
    我也遇到这个问题,在 tcp 下,无法透传真实 ip
    Toadair
        42
    Toadair  
       2021-05-27 16:08:33 +08:00
    大佬们有人解决这个问题吗,谷歌了好几个例子均未能实现
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     826 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 48ms UTC 20:20 PVG 04:20 LAX 12:20 JFK 15:20
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86