让 socat 同时监听 IPv4 和 IPv6 栈

让 socat 同时监听 IPv4 和 IPv6 栈

前几天换了供应商,他们只分配 DSlite 连接。我以为这样就好了。问题是 - 我想从网络外部访问我的一些东西,现在我有了原生 IPv6,这应该没那么麻烦了。

我面临的新主要问题是,我无法假设漫游到任何地方都能实现这一点,因此大多数时候我会尝试从仅 IPv4 的入口点进行访问。$ socat我的朋友找到了答案,因为我可以使用真正的双栈连接访问一个盒子 - 因此从仅 IPv4 的连接访问我的 IPv6 就像$ socat UDP4-LISTEN:sourceport,fork,su=nobody UDP6:my-ipv6-hostname-behind.cgn:targetport在双栈机器上运行然后my-dualstack-hostna.me:sourceport从外部连接一样简单。

现在,$ netstat -tulpen | grep sourceport在双栈机器上只显示一个 UDP4 监听器 - 所以我现在的问题是:

  • 从仅 IPv6 连接访问需要我连接到my-ipv6-hostname-behind.cgn:targetport
  • 从仅 IPv4 连接访问需要我连接到my-dualstack-hostna.me:sourceport
  • 通过 DS(-lite) 连接访问可以同时使用两者,但最好使用直接 IPv6 路由

因此,如果能够my-dualstack-hostna.me:sourceport同时用于 IPv4 和 IPv6 连接,并且每次移动笔记本电脑或手机时都不需要 root 更新配置,那就太好了!如何让socat两者同时监听?一定有办法!$ netstat -tulpen | grep ":22"DS 机器上显示以下内容:

tcp        0      0 0.0.0.0:22 […]
tcp6       0      0 :::22      […]

答案1

我遇到了同样的问题 - 你可以通过运行两个 socat 实例来解决这个问题,一个监听 ipv4,一个监听同一个 ipv6 端口将每个绑定到其各自的地址, 像这样:

socat UDP4-LISTEN:sourceport,bind=<ipv4-addr>,fork,su=nobody UDP6:my-ipv6-hostname-behind.cgn:targetport

socat UDP6-LISTEN:sourceport,bind=<ipv6-addr>,fork,su=nobody UDP6:my-ipv6-hostname-behind.cgn:targetport

答案2

您可以将 socat 配置为同时监听 IPv4 和 IPv6,但与直觉相反的是,始终使用“TCP6-LISTENER”或“UDP6-LISTENER”地址格式。这会导致 socat 以双栈方式监听。这是因为默认情况下,当套接字已绑定时,Linux(我怀疑 BSD 也是如此)也会接受 IPv4 ::

$ socat -v tcp6-listen:8000,fork,max-children=500,reuseaddr exec:"$(which cat)"

我们可以看到socat现在支持双栈。

$ ss -ntpl | rg socat
LISTEN 0      5                  *:8000             *:*    users:(("socat",pid=1568208,fd=5))

$ echo "test" | nc 127.0.0.1 8000
test
^C

$ echo "test" | nc ::1 8000
test
^C

如果你在实际只需要 IPv6 的环境中使用 socat,则可以传递该ipv6only选项。这将设置IPV6_V6ONLY套接字选项,该选项在IPv6(7)

IPV6_V6ONLY (since Linux 2.4.21 and 2.6)  
        If this flag is set to true (nonzero), then the  socket  is  re‐  
        stricted  to  sending  and receiving IPv6 packets only.  In this  
        case, an IPv4 and an IPv6 application can bind to a single  port  
        at the same time.

        If this flag is set to false (zero), then the socket can be used
        to send and receive packets to and from an IPv6  address  or  an
        IPv4-mapped IPv6 address.

$ socat -v tcp6-listen:8000,fork,max-children=500,reuseaddr,ipv6only exec:"$(which cat)

然后我们可以观察到这个变化:

$ ss -ntpl | rg socat
LISTEN 0      5               [::]:8000          [::]:*    users:(("socat",pid=1573995,fd=5))

$ echo "test" | nc 127.0.0.1 8000

$ echo "test" | nc ::1 8000
test
^C

相关内容