V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
Raul7
V2EX  ›  NGINX

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

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

    客户端( 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 $proxy_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   ·   实用小工具   ·   1132 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 23:47 · PVG 07:47 · LAX 15:47 · JFK 18:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.