1个不稳定版本
0.1.0 | 2022年8月9日 |
---|
#3 在 #forwarder
22KB
381 行
netns_tcp_bridge
特殊TCP转发器(代理),监听部分和连接部分可以通过setns(2)
调用移动到其他Linux网络命名空间。
它某种程度上类似于使用成对的socat,每个都在不同的netns中。
socat tcp-l:1234,fork,reuseaddr unix:/path/to/unix-socket-shared-between-namespaces.sock
socat unix-listen:/path/to/unix-socket-shared-between-namespaces.sock tcp:127.0.0.1:1234
它通过创建两个进程:监听器和连接器,并通过将监听器上的连接套接字(SCM_RIGHTS
)通过socketpair(2)
传递到连接器进程来实现。每个部分都可以移动到自己的网络命名空间。
使用cargo build --release
构建,或从GitHub发行版下载。
示例会话
usual_netns# unshare --net xterm&
usual_netns# dig +short example.com | new_netns# ip link set lo up
93.184.216.34 |
usual_netns# ip route get 93.184.216.34 | new_netns# ip route get 93.184.216.34
93.184.216.34 via 192.168.0.1 dev wlan0 | RTNETLINK answers: Network is unreachable
src 192.168.0.185 uid 0 cache |
usual_netns# curl --head http://93.184.216.34/ | new_netns# curl --head http://93.184.216.34/
HTTP/1.1 404 Not Found | curl: (7) Couldn't connect to server
Content-Type: text/html | new_netns# curl --head http://127.0.0.1/
Date: Mon, 08 Aug 2022 23:48:10 GMT | curl: (7) Failed to connect to 127.0.0.1
Server: ECS (nyb/1D07) | port 80: Connection refused
Content-Length: 345 | new_netns# echo $$
| 6448
usual_netns# netns_tcp_bridge -l 127.0.0.1:80 \ |
-f /proc/6448/ns/net \ |
-c 93.184.216.34:80 |
| new_netns# curl --head http://127.0.0.1/
| HTTP/1.1 404 Not Found
| Content-Type: text/html
| Date: Mon, 08 Aug 2022 23:53:32 GMT
| Server: ECS (nyb/1D2E)
| Content-Length: 345
局限性
- 像FIN/RST区分、OOB数据这样的复杂TCP特性没有得到保留。转发引擎是Tokio的基本
copy_bidirectional
。 - 单线程操作可能会限制性能。
- 没有使用
io_uring
也限制了性能 - 每个转发的数据包都是两个或三个系统调用。
请注意,我已经实现了更多模式(例如使用原始FD),但只测试了最简单的模式。
使用说明
netns_tcp_bridge --help
Usage: netns_tcp_bridge [OPTIONS]
Optional arguments:
-h, --help
-l, --listen LISTEN Socket address (e.g. `127.0.0.1:1234` or `[::1]:1234`) to bind socket to.
-L, --listen-fd LISTEN-FD File descriptor to use as a listening socket
-S, --preaccepted-fd PREACCEPTED-FD
File descriptor to use as a single connected client (skip listening and accepting loop)
-c, --connect CONNECT Socket address to forward incoming connections to.
-C, --connect-fd CONNECT-FD
Pre-connected file descriptor to forward just one accepted connection to
-f, --listen-netns-file LISTEN-NETNS-FILE
Path to a nsfs file with mounted network namespace where listening part of the forwarder should operate. E.g. /proc/1234/ns/net
-F, --listen-netns-fd LISTEN-NETNS-FD
Already opened file descriptor to use for the `setns` call on listening side
-t, --connect-netns-file CONNECT-NETNS-FILE
Path to a nsfs netns file to `setns` on the connecting side
-T, --connect-netns-fd CONNECT-NETNS-FD
Already opened file descriptor to use for the `setns` call on the connecting side
依赖项
~6–15MB
~179K SLoC