{"id":15373047,"url":"https://github.com/vi/netns_tcp_bridge","last_synced_at":"2025-04-15T12:31:42.907Z","repository":{"id":55640434,"uuid":"522737281","full_name":"vi/netns_tcp_bridge","owner":"vi","description":"Linux CLI tool to forward TCP connections from one network namespace to another network namespace","archived":false,"fork":false,"pushed_at":"2023-11-03T22:54:18.000Z","size":16,"stargazers_count":13,"open_issues_count":1,"forks_count":3,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-28T21:12:10.628Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-08-08T23:25:39.000Z","updated_at":"2025-02-11T13:26:27.000Z","dependencies_parsed_at":"2024-10-16T13:01:16.665Z","dependency_job_id":null,"html_url":"https://github.com/vi/netns_tcp_bridge","commit_stats":{"total_commits":6,"total_committers":1,"mean_commits":6.0,"dds":0.0,"last_synced_commit":"28787ddf8ddfcb1897bb1771d1b265120b7ea7ad"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vi%2Fnetns_tcp_bridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vi%2Fnetns_tcp_bridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vi%2Fnetns_tcp_bridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vi%2Fnetns_tcp_bridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vi","download_url":"https://codeload.github.com/vi/netns_tcp_bridge/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249072264,"owners_count":21208150,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-01T13:54:09.530Z","updated_at":"2025-04-15T12:31:42.694Z","avatar_url":"https://github.com/vi.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# netns_tcp_bridge\n\nSpecial TCP forwarder (proxy) where listening part and connecing part can move to other \nLinux network namespaces using `setns(2)` call.\n\nIt is somewhat analogous to using a pair of [socat][s]s, each in different netns.\n\n* `socat tcp-l:1234,fork,reuseaddr unix:/path/to/unix-socket-shared-between-namespaces.sock`\n* `socat unix-listen:/path/to/unix-socket-shared-between-namespaces.sock tcp:127.0.0.1:1234`\n\nIt 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.\n\nBuild it with `cargo build --release` or download it from [Github releases][gr].\n\n# Example session\n\n```\nusual_netns# unshare --net xterm\u0026\nusual_netns# dig +short example.com               | new_netns# ip link set lo up\n 93.184.216.34                                    | \nusual_netns# ip route get 93.184.216.34           | new_netns# ip route get 93.184.216.34 \n 93.184.216.34 via 192.168.0.1 dev wlan0          |  RTNETLINK answers: Network is unreachable\n    src 192.168.0.185 uid 0   cache               |\nusual_netns# curl --head http://93.184.216.34/    | new_netns# curl --head http://93.184.216.34/\n HTTP/1.1 404 Not Found                           |  curl: (7) Couldn't connect to server\n Content-Type: text/html                          | new_netns# curl --head http://127.0.0.1/\n Date: Mon, 08 Aug 2022 23:48:10 GMT              |  curl: (7) Failed to connect to 127.0.0.1\n Server: ECS (nyb/1D07)                           |         port 80: Connection refused\n Content-Length: 345                              | new_netns# echo $$\n                                                  |  6448\nusual_netns# netns_tcp_bridge -l 127.0.0.1:80 \\   |\n                   -f /proc/6448/ns/net \\         |\n                   -c 93.184.216.34:80            |                          \n                                                  | new_netns# curl --head http://127.0.0.1/\n                                                  |  HTTP/1.1 404 Not Found\n                                                  |  Content-Type: text/html\n                                                  |  Date: Mon, 08 Aug 2022 23:53:32 GMT\n                                                  |  Server: ECS (nyb/1D2E)\n                                                  |  Content-Length: 345\n```\n\n\n# Limitations\n\n* Tricky TCP features like FIN/RST distinction, OOB data are not preserved. Forwarding engine is a basic Tokio's [`copy_bidirectional`][cb].\n* Single-threaded operation may limit performance.\n* Non-usage of `io_uring` also limits performance - each forwarded packet is two or three syscalls.\n\nNote that I have implemented more modes (e.g. using raw FDs), but have tested only the most straightforward mode.\n\n[cb]:https://docs.rs/tokio/latest/tokio/io/fn.copy_bidirectional.html\n[s]:http://www.dest-unreach.org/socat/\n[gr]:https://github.com/vi/netns_tcp_bridge/releases/\n\n# Usage message\n\n```\nnetns_tcp_bridge --help\nUsage: netns_tcp_bridge [OPTIONS]\n\nOptional arguments:\n  -h, --help\n  -l, --listen LISTEN        Socket address (e.g. `127.0.0.1:1234` or `[::1]:1234`) to bind socket to.\n  -L, --listen-fd LISTEN-FD  File descriptor to use as a listening socket\n  -S, --preaccepted-fd PREACCEPTED-FD\n                             File descriptor to use as a single connected client (skip listening and accepting loop)\n  -c, --connect CONNECT      Socket address to forward incoming connections to.\n  -C, --connect-fd CONNECT-FD\n                             Pre-connected file descriptor to forward just one accepted connection to\n  -f, --listen-netns-file LISTEN-NETNS-FILE\n                             Path to a nsfs file with mounted network namespace where listening part of the forwarder should operate. E.g. /proc/1234/ns/net\n  -F, --listen-netns-fd LISTEN-NETNS-FD\n                             Already opened file descriptor to use for the `setns` call on listening side\n  -t, --connect-netns-file CONNECT-NETNS-FILE\n                             Path to a nsfs netns file to `setns` on the connecting side\n  -T, --connect-netns-fd CONNECT-NETNS-FD\n                             Already opened file descriptor to use for  the `setns` call on the connecting side\n```\n\n# See also\n\n* [socketbox](https://github.com/PHJArea217/socketbox)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvi%2Fnetns_tcp_bridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvi%2Fnetns_tcp_bridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvi%2Fnetns_tcp_bridge/lists"}