Skip to content

Linux CLI tool to forward TCP connections from one network namespace to another network namespace

License

Notifications You must be signed in to change notification settings

vi/netns_tcp_bridge

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

netns_tcp_bridge

Special TCP forwarder (proxy) where listening part and connecing part can move to other Linux network namespaces using setns(2) call.

It is somewhat analogous to using a pair of socats, each in different 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

It works by forking into two processes: listener and connector and by passing (SCM_RIGHTS) connected sockets from listener over a socketpair(2) to the connector process. Each part can be moved into each own network namespace.

Build it with cargo build --release or download it from Github releases.

Example session

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

Limitations

  • Tricky TCP features like FIN/RST distinction, OOB data are not preserved. Forwarding engine is a basic Tokio's copy_bidirectional.
  • Single-threaded operation may limit performance.
  • Non-usage of io_uring also limits performance - each forwarded packet is two or three syscalls.

Note that I have implemented more modes (e.g. using raw FDs), but have tested only the most straightforward mode.

Usage message

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

See also

About

Linux CLI tool to forward TCP connections from one network namespace to another network namespace

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages