V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
ppxppx
V2EX  ›  分享创造

一个 TCP/UDP 端口复用器,根据第一个包的内容用正则表达式来确定转发的目标

  •  
  •   ppxppx · 2023-05-28 10:03:46 +08:00 · 2507 次点击
    这是一个创建于 550 天前的主题,其中的信息可能已经有所发展或是发生改变。

    github: https://github.com/lidotcircle/portForwarder

    应用协议复用器

    应用协议复用器是一种工具,它允许您根据客户端发送的第一个数据包中的正则表达式模式匹配,将 TCP 或 UDP 流量转发到不同的地址。

    使用方法

    可以从源代码构建此工具,或者从发布页面下载名为 portfd 的预编译二进制文件。

    可以使用简单的命令行参数运行 portfd ,请使用以下语法:portfd <local-bind> <remote>。 在这种情况下,需要指定监听地址和远程地址。 对于更高级的用法,portfd 可以使用支持更复杂规则的配置文件启动。以下是一个使用 YAML 格式的配置文件示例:

    forwarders:
      - local: 0.0.0.0:8808
        # 指定 'remoteMap' 或 'remote'
        remoteMap:
          - pattern: "[http:localhost]"
            remote: 192.168.44.43:5445
          - pattern: "[https:baidu.com]"
            remote: "39.156.66.10:443"
          - pattern: "[ssh]"
            remote: "192.168.44.43:22"
          - pattern: .*
            remote: 192.168.100.46:3389
        remote: <remote-address/127.0.0.1:2233>
        enable_tcp: true # 默认为 true
        enable_udp: true # 默认为 true
        conn_bufsize: 2MB
        max_connections: 10000 # 可选
        allow_nets: # 可选的白名单
          - 127.0.0.0/24
    

    pattern字段支持四种格式,所有格式都将转换为正则表达式:

    • [http] 或 [http:domain_name]:仅将 HTTP 流量或与 domain_name 匹配的 HTTP 请求的主机名转发到指定的远程地址。
    • [https:domain_name]:匹配 HTTPS 流量中客户端 Hello 中的 SNI (服务器名称指示)。
    • [ssh]:仅将 SSH 流量转发。
    • 任意正则表达式:仅将与此正则表达式匹配的首个接收到的数据包的流量转发。
    27 条回复    2023-06-01 09:04:21 +08:00
    happyn
        1
    happyn  
       2023-05-28 10:06:15 +08:00   ❤️ 1
    很有用的小工具,这样一些服务可以根据流量特征,做负载均衡了;
    Tink
        2
    Tink  
       2023-05-28 10:42:32 +08:00   ❤️ 1
    6
    一个端口既翻墙又跑网站顺便还能 ssh
    myqoo
        3
    myqoo  
       2023-05-28 11:01:11 +08:00   ❤️ 1
    这个用 iptables 可以实现吗?
    ppxppx
        4
    ppxppx  
    OP
       2023-05-28 11:12:41 +08:00
    @myqoo #3 应该不行,这个需要根据流量的内容来决定转发的目标,我问 chatgpt 得到的答案是 iptable 不支持这个功能。

    ```
    No, iptables cannot directly route traffic based on the content of the traffic. iptables is a tool used for configuring the firewall rules in the Linux kernel's netfilter framework. It primarily operates at the network layer (Layer 3) and transport layer (Layer 4) of the network stack, inspecting factors such as source and destination IP addresses, ports, and protocols.
    ```

    而且这个工具用 Rust 写的,所以可以在 Windows 下用。
    IDAEngine
        5
    IDAEngine  
       2023-05-28 11:28:47 +08:00   ❤️ 1
    @ppxppx iptables 可以根据流量特征转发特定目标,不过要制定一套 tag 规则
    listenfree
        6
    listenfree  
       2023-05-28 11:49:47 +08:00   ❤️ 1
    nftables 应该可行吧,昨天学了下,感觉比 iptables 简单。
    ppxppx
        7
    ppxppx  
    OP
       2023-05-28 11:55:27 +08:00
    @IDAEngine 哈哈,看来 chatgpt 还是不可尽信。不过 iptables 上手难度还是挺高的,看了半天也没 tag 规则理解怎么用
    ppxppx
        8
    ppxppx  
    OP
       2023-05-28 11:59:35 +08:00
    @listenfree #6 确实,而且 nftables 语法看着比 iptables 友好太多
    leonshaw
        9
    leonshaw  
       2023-05-28 12:06:42 +08:00
    这是四层代理功能,iptables/nftables 应该不行。
    不知道对第一个包不够的情况怎么处理的,比如 http url 过长导致 host 第一次没读到。
    myqoo
        10
    myqoo  
       2023-05-28 12:12:27 +08:00
    @leonshaw 第一个包长度不够先暂存这就可以。读够缓冲区再识别。
    myqoo
        11
    myqoo  
       2023-05-28 12:13:09 +08:00
    能用 iptables 的话可以保留原地址,否则日志里的原地址都是本地 ip 。
    ppxppx
        12
    ppxppx  
    OP
       2023-05-28 12:16:14 +08:00
    @leonshaw 这种情况还没考虑,感觉要处理这种情形挺复杂的。
    myqoo
        13
    myqoo  
       2023-05-28 12:16:59 +08:00
    像 ngixn 里可以用 proxy_bind $remote_addr transparent; 转发时保留原始 IP ,不过这个特征貌似不是跨平台的。
    ppxppx
        14
    ppxppx  
    OP
       2023-05-28 12:20:27 +08:00
    @myqoo #10 主要是不知道客户端什么时候才能把包发完,所以一直保留这个包可能导致内存爆炸。
    myqoo
        15
    myqoo  
       2023-05-28 12:22:36 +08:00   ❤️ 1
    @ppxppx 加个最大长度+最大时间就可以。最大长度内没出现,或超时,就断开。这种都是极小概率事件。
    ppxppx
        16
    ppxppx  
    OP
       2023-05-28 12:24:03 +08:00
    @myqoo #15 这倒是可以考虑,有时间我去试试看
    leonshaw
        17
    leonshaw  
       2023-05-28 12:29:01 +08:00
    @ppxppx
    是的,我之前写类似工具的时候就很头疼,不同协议区别太大了,加超时又可能影响体验。举个极端例子,telnet 客户端可能一开始根本不发数据包,而是先等服务端给个提示符。
    ppxppx
        18
    ppxppx  
    OP
       2023-05-28 12:56:04 +08:00
    @leonshaw 这种服务端先发就没办法,最多就直接转发
    leo97
        19
    leo97  
       2023-05-28 14:05:39 +08:00 via Android
    haproxy 可以做到
    leeyuzhe
        20
    leeyuzhe  
       2023-05-29 10:02:50 +08:00
    不通协议的粘包如何处理?
    ppxppx
        21
    ppxppx  
    OP
       2023-05-29 12:03:41 +08:00 via Android
    @leeyuzhe 收到的第一个 tcp 包的数据越多应该更有助于判断协议类型,所以不需要处理吧
    julyclyde
        22
    julyclyde  
       2023-05-30 11:19:53 +08:00
    @leeyuzhe 粘包是一种编程错误
    和转发没什么关系
    leeyuzhe
        23
    leeyuzhe  
       2023-05-30 13:26:36 +08:00
    @ppxppx #21
    @julyclyde
    对对对,粘包跟 lz 这个项目无关 ,是我想错了。
    julyclyde
        24
    julyclyde  
       2023-05-30 19:21:18 +08:00
    @IDAEngine 首先 iptables 就不负责转发吧,何谈“根据规则”?
    etnperlong
        25
    etnperlong  
       2023-05-31 23:14:38 +08:00
    不错不错 已 star
    想提个需求 看看大佬能不能支持一下 RDP ?
    ppxppx
        26
    ppxppx  
    OP
       2023-05-31 23:46:54 +08:00 via Android
    @etnperlong #25 我之前有看过相关文档,不过 rdp 的包有点复杂,还得再研究研究
    ppxppx
        27
    ppxppx  
    OP
       2023-06-01 09:04:21 +08:00 via Android   ❤️ 1
    @etnperlong #25 刚刚加了对 rdp 的支持
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4989 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 09:51 · PVG 17:51 · LAX 01:51 · JFK 04:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.