{"id":15372998,"url":"https://github.com/vi/wgslirpy","last_synced_at":"2025-04-15T11:32:50.358Z","repository":{"id":187964220,"uuid":"677865669","full_name":"vi/wgslirpy","owner":"vi","description":"User-space Wireguard gateway allowing sharing network connection from environment where usual routing rules are inaccessible.","archived":false,"fork":false,"pushed_at":"2023-09-08T15:06:17.000Z","size":110,"stargazers_count":29,"open_issues_count":0,"forks_count":7,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-10T06:54:07.855Z","etag":null,"topics":["boringtun","networking","nonroot-user","onetun","slirp","smoltcp","userspace-networking","wireguard"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"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":null,"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":"2023-08-12T22:46:30.000Z","updated_at":"2025-02-11T13:26:44.000Z","dependencies_parsed_at":null,"dependency_job_id":"ac02d5e2-e0ce-4d8b-8267-b03f5bad9697","html_url":"https://github.com/vi/wgslirpy","commit_stats":{"total_commits":34,"total_committers":2,"mean_commits":17.0,"dds":0.02941176470588236,"last_synced_commit":"6805933f3e6f88f3cd8d1106a135d7d53eb198ea"},"previous_names":["vi/wgslirpy"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vi%2Fwgslirpy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vi%2Fwgslirpy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vi%2Fwgslirpy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vi%2Fwgslirpy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vi","download_url":"https://codeload.github.com/vi/wgslirpy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249061202,"owners_count":21206467,"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":["boringtun","networking","nonroot-user","onetun","slirp","smoltcp","userspace-networking","wireguard"],"created_at":"2024-10-01T13:53:58.097Z","updated_at":"2025-04-15T11:32:50.070Z","avatar_url":"https://github.com/vi.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# wgslirpy\n\nA command line tool (and a Rust library) for accepting incoming connections within a Wireguard link and routing them to external network using usual opeating system's socket API.  \nThis allows creating a sort of VPN server without root access, e.g. from Android app or when using unprivileged containers.\n\n\u003cimg src=\"wgslirp.svg\" alt=\"Diagram depicting operation of Wgslirpy\" width=\"40%\"/\u003e\n\n## Features\n\n* Maintaining Wireguard connection with one peer, using [Boringtun](https://github.com/cloudflare/boringtun) library.\n* Decoding incoming TCP or UDP connections using [smoltcp](https://github.com/smoltcp-rs/smoltcp) library\n* Forwarding TCP and UDP connections from Wireguard to external world, exchanging traffic between userspace and real sockets.\n* For UDP, hole punching / NAT traversal should work (not tested though)\n* For TCP, half-closed connections and backpressure should work\n* Crude DNS server for resolving IPv4 and IPv6 addresses using host's name resolution mechanism.\n* Reverse mode for specific TCP and UDP ports - forwarding connections from host to Wireguard.\n\n## Limitations\n\n* No ICMP (except of pings to specific address for testing). This affects UDP's \"port unreachable\"s.\n\n## Demo session\n\n\u003cdetails\u003e\u003csummary\u003eSetup\u003c/summary\u003e\n\n```\npeer# wg genkey\n4Khaa5tgPI9NJsO2R896Yd6748k9fW4aapGZnIcUM14=\npeer# wg pubkey \u003c\u003c\u003c 4Khaa5tgPI9NJsO2R896Yd6748k9fW4aapGZnIcUM14=\nrPpCjWzIv/yAtZZi+C/pVprie8D0QaGlPtJXlDi6bmI=\n\ngateway$ wg genkey\nSG43Zi0wGp4emfJ/XpTnnmtnK8SSjjIHOc3Zh37c928=\ngateway$ wg pubkey \u003c\u003c\u003c SG43Zi0wGp4emfJ/XpTnnmtnK8SSjjIHOc3Zh37c928=\nMR2RF5Tp+6BKt9k+deKg1GqR3re3ckJKti+uwZA84DU=\n\npeer# ip link add wgslirpyspeer type wireguard\npeer# wg set wgslirpyspeer listen-port 9796 private-key \u003c(echo 4Khaa5tgPI9NJsO2R896Yd6748k9fW4aapGZnIcUM14=) peer MR2RF5Tp+6BKt9k+deKg1GqR3re3ckJKti+uwZA84DU= allowed-ips 0.0.0.0/0,::/0\npeer# ip netns add testing-wgslirp\npeer# ip link set wgslirpyspeer netns testing-wgslirp\npeer# ip netns exec testing-wgslirp ip link set wgslirpyspeer up\npeer# ip netns exec testing-wgslirp ip addr add 192.168.76.1/32 dev wgslirpyspeer\npeer# ip netns exec testing-wgslirp ip addr add fc00::01/128 dev wgslirpyspeer\npeer# ip netns exec testing-wgslirp route -4 add default dev wgslirpyspeer\npeer# ip netns exec testing-wgslirp route -6 add default dev wgslirpyspeer\npeer# mkdir -p /etc/netns/testing-wgslirp\npeer# echo nameserver 192.168.72.2 \u003e /etc/netns/testing-wgslirp/resolv.conf\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eActivation\u003c/summary\u003e\n\n```\ngateway$ RUST_LOG=debug wgslirpy --private-key SG43Zi0wGp4emfJ/XpTnnmtnK8SSjjIHOc3Zh37c928= -b 127.0.0.1:9797 --peer-key rPpCjWzIv/yAtZZi+C/pVprie8D0QaGlPtJXlDi6bmI= --peer-endpoint 127.0.0.1:9796 --keepalive-interval 10 --dns 192.168.72.2:53 --pingable 192.168.72.2\nDEBUG boringtun::noise: Sending handshake_initiation\nDEBUG boringtun::noise: Received handshake_response local_idx=1 remote_idx=2743606023\nDEBUG boringtun::noise: New session session=1\nDEBUG boringtun::noise: Sending keepalive\n\npeer# ip netns exec testing-wgslirp wg\ninterface: wgslirpyspeer\n  public key: rPpCjWzIv/yAtZZi+C/pVprie8D0QaGlPtJXlDi6bmI=\n  private key: (hidden)\n  listening port: 9796\n\npeer: MR2RF5Tp+6BKt9k+deKg1GqR3re3ckJKti+uwZA84DU=\n  endpoint: 127.0.0.1:9797\n  allowed ips: 0.0.0.0/0, ::/0\n  latest handshake: 46 seconds ago\n  transfer: 340 B received, 92 B sent\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eTesting\u003c/summary\u003e\n\n```\npeer# # ip netns exec testing-wgslirp ping -c 2 192.168.72.2\n64 bytes from 192.168.72.2: icmp_seq=1 ttl=64 time=0.705 ms\n64 bytes from 192.168.72.2: icmp_seq=2 ttl=64 time=0.435 ms\n\ngateway$ \nINFO wgslirpy::router: New NAT entry for Pingable\nDEBUG wgslirpy::router: Finished serving Pingable\n\npeer# ip netns exec testing-wgslirp curl http://example.com/\n\u003c!doctype html\u003e\n...\n\u003c/html\u003e\n\ngateway$\nDEBUG wgslirpy::router::serve_dns: DNS query example.com:0\nDEBUG wgslirpy::router: Sending DNS reply\n\nINFO wgslirpy::router: New NAT entry for Tcp { client_side: Endpoint { addr: Ipv4(Address([192, 168, 76, 1])), port: 48004 }, external_side: Endpoint { addr: Ipv4(Address([93, 184, 216, 34])), port: 80 } }\nDEBUG wgslirpy::router::serve_tcp: Connected to upstream TCP\nDEBUG wgslirpy::router::serve_tcp: Accepted the connection\nDEBUG wgslirpy::router::serve_tcp: EOF received from client\nDEBUG wgslirpy::router::serve_tcp: Shutdown finished\nDEBUG wgslirpy::router::serve_tcp: EOF\nDEBUG wgslirpy::router::serve_tcp: Client TCP socket no longer active\nDEBUG boringtun::noise::timers: KEEPALIVE(PERSISTENT_KEEPALIVE)\nDEBUG wgslirpy::router: Finished serving Tcp { client_side: Endpoint { addr: Ipv4(Address([192, 168, 76, 1])), port: 48004 }, external_side: Endpoint { addr: Ipv4(Address([93, 184, 216, 34])), port: 80 } }\n\npeer# ip netns exec testing-wgslirp dig +short github.com @8.8.8.8\n140.82.112.3\n\ngateway$\n01:26:14 INFO wgslirpy::router: New NAT entry for Udp\n...\n01:27:46 DEBUG wgslirpy::router::serve_udp: Timed out a UDP connection\n```\n\u003c/details\u003e\n\n## Installation\n\nDownload a pre-built executable from [Github releases](https://github.com/vi/wgslirpy/releases) or install from source code with `cargo install --path .`  or `cargo install wgslirpy`.\n\n## CLI options\n\n\u003cdetails\u003e\u003csummary\u003e wgslirpy --help output\u003c/summary\u003e\n\n```\nUsage: wgslirpy [-k \u003cprivate-key\u003e] [-f \u003cprivate-key-file\u003e] -K \u003cpeer-key\u003e [-p \u003cpeer-endpoint\u003e] [-a \u003ckeepalive-interval\u003e] -b \u003cbind-ip-port\u003e [-D \u003cdns\u003e] [-P \u003cpingable\u003e] [--mtu \u003cmtu\u003e] [--tcp-buffer-size \u003ctcp-buffer-size\u003e] [--transmit-queue-capacity \u003ctransmit-queue-capacity\u003e] [-u \u003cincoming-udp...\u003e] [-t \u003cincoming-tcp...\u003e]\n\nExpose internet access without root using Wireguard\n\nOptions:\n  -k, --private-key main private key of this Wireguard node, base64-encoded\n  -f, --private-key-file\n                    main private key of this Wireguard node (content of a\n                    specified file), base64-encoded\n  -K, --peer-key    peer's public key\n  -p, --peer-endpoint\n                    address of the peer's UDP socket, where to send keepalives\n  -a, --keepalive-interval\n                    keepalive interval, in seconds\n  -b, --bind-ip-port\n                    where to bind our own UDP socket for Wireguard connection\n  -D, --dns         use this UDP socket address as a simple A/AAAA-only DNS\n                    server within Wireguard network\n  -P, --pingable    reply to ICMP pings on this single address within Wireguard\n                    network\n  --mtu             maximum transfer unit to use for TCP. Default is 1420.\n  --tcp-buffer-size in-application socket TCP buffer size. Note that operating\n                    system socket buffer also applies.\n  --transmit-queue-capacity\n                    nubmer of outgoing (to wireguard) packets to hold in a queue\n  -u, --incoming-udp\n                    forward this host UDP port into Wireguard network. You need\n                    to specify triplet of socket addresses: host, source\n                    (optional) and dest. Host address is address to bind\n                    operating system socket to. source and dest addreses are\n                    used within Wireguard network. Example: -u\n                    0.0.0.0:1234,10.0.2.1:1234,10.0.2.15:1234\n  -t, --incoming-tcp\n                    forward this host TCP port into Wireguard network. You need\n                    to specify triplet of socket addresses: host, source\n                    (optional) and dest. Host address is address to bind\n                    operating system socket to. source and dest addreses are\n                    used within Wireguard network. If source port is 0,\n                    roundrobin is used. Example: -t 0.0.0.0:1234,,10.0.2.15:1234\n  --help            display usage information\n```\n\u003c/details\u003e\n\n## Wireguardless (GUE/FOU) mode\n\nYou can opt out Wireguard layer using special keywords `INSECURE` and `GUE` as local and peer keys respectively.\nThis way wgslirpy would just send IPv4/IPv6 packets directly as UDP datagrams.\n\n\u003cdetails\u003e\u003csummary\u003eExample session\u003c/summary\u003e\n\n```\ngateway$ wgslirpy -k INSECURE -K GUE -b 127.0.0.1:6556 --dns 10.0.2.1:53 -P 10.0.2.1\npeer# ip fou add port 6555 gue local 127.0.0.1 peer 127.0.0.1 peer_port 6556 dev lo\npeer# ip link add guegue type sit remote 127.0.0.1 local 127.0.0.1 encap gue encap-sport 6555 encap-dport 6556 encap-csum\npeer# ip link set guegue netns testing-wgslirp\npeer# ip netns exec testing-wgslirp ip link set guegue up\npeer# ip netns exec testing-wgslirp ip addr add 10.0.2.15/24 dev guegue\npeer# ip netns exec testing-wgslirp ip route add default dev guegue\npeer# ip netns exec testing-wgslirp ping 10.0.2.1\n64 bytes from 10.0.2.1: icmp_seq=4 ttl=64 time=2.53 ms\n...\n```\n\nYou can also use simpler mode with `ipip` and `fou` instead of `sit` and `gue`, but that wouldn't support IPv6.\n\n\u003c/details\u003e\n\n## See also\n\n* [onetun](https://github.com/aramperes/onetun) - Similar idea, but is designed to forward connections _to_ Wireguard instead of _from_ Wireguard.\n* [SLiRP](https://en.wikipedia.org/wiki/Slirp) - Similar idea, but with PPP (a stream-based connection) instead of packet-based Wireguard.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvi%2Fwgslirpy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvi%2Fwgslirpy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvi%2Fwgslirpy/lists"}