wgslirpy

A 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.
This allows creating a sort of VPN server without root access, e.g. from Android app or when using unprivileged containers.

Diagram depicting operation of Wgslirpy

Features

Limitations

Demo session

Setup

``` peer# wg genkey 4Khaa5tgPI9NJsO2R896Yd6748k9fW4aapGZnIcUM14= peer# wg pubkey <<< 4Khaa5tgPI9NJsO2R896Yd6748k9fW4aapGZnIcUM14= rPpCjWzIv/yAtZZi+C/pVprie8D0QaGlPtJXlDi6bmI=

gateway$ wg genkey SG43Zi0wGp4emfJ/XpTnnmtnK8SSjjIHOc3Zh37c928= gateway$ wg pubkey <<< SG43Zi0wGp4emfJ/XpTnnmtnK8SSjjIHOc3Zh37c928= MR2RF5Tp+6BKt9k+deKg1GqR3re3ckJKti+uwZA84DU=

peer# ip link add wgslirpyspeer type wireguard peer# wg set wgslirpyspeer listen-port 9796 private-key <(echo 4Khaa5tgPI9NJsO2R896Yd6748k9fW4aapGZnIcUM14=) peer MR2RF5Tp+6BKt9k+deKg1GqR3re3ckJKti+uwZA84DU= allowed-ips 0.0.0.0/0,::/0 peer# ip netns add testing-wgslirp peer# ip link set wgslirpyspeer netns testing-wgslirp peer# ip netns exec testing-wgslirp ip link set wgslirpyspeer up peer# ip netns exec testing-wgslirp ip addr add 192.168.76.1/32 dev wgslirpyspeer peer# ip netns exec testing-wgslirp ip addr add fc00::01/128 dev wgslirpyspeer peer# ip netns exec testing-wgslirp route -4 add default dev wgslirpyspeer peer# ip netns exec testing-wgslirp route -6 add default dev wgslirpyspeer peer# mkdir -p /etc/netns/testing-wgslirp peer# echo nameserver 192.168.72.2 > /etc/netns/testing-wgslirp/resolv.conf ```

Activation

``` gateway$ RUSTLOG=debug wgslirpy --private-key SG43Zi0wGp4emfJ/XpTnnmtnK8SSjjIHOc3Zh37c928= -b 127.0.0.1:9797 --peer-key rPpCjWzIv/yAtZZi+C/pVprie8D0QaGlPtJXlDi6bmI= --keepalive-interval 10 --dns 192.168.72.2:53 --pingable 192.168.72.2 DEBUG boringtun::noise: Sending handshakeinitiation DEBUG boringtun::noise: Received handshakeresponse localidx=1 remote_idx=2743606023 DEBUG boringtun::noise: New session session=1 DEBUG boringtun::noise: Sending keepalive

peer# ip netns exec testing-wgslirp wg interface: wgslirpyspeer public key: rPpCjWzIv/yAtZZi+C/pVprie8D0QaGlPtJXlDi6bmI= private key: (hidden) listening port: 9796

peer: MR2RF5Tp+6BKt9k+deKg1GqR3re3ckJKti+uwZA84DU= endpoint: 127.0.0.1:9797 allowed ips: 0.0.0.0/0, ::/0 latest handshake: 46 seconds ago transfer: 340 B received, 92 B sent ```

Testing

``` peer# # ip netns exec testing-wgslirp ping -c 2 192.168.72.2 64 bytes from 192.168.72.2: icmpseq=1 ttl=64 time=0.705 ms 64 bytes from 192.168.72.2: icmpseq=2 ttl=64 time=0.435 ms

gateway$ INFO wgslirpy::router: New NAT entry for Pingable DEBUG wgslirpy::router: Finished serving Pingable

peer# ip netns exec testing-wgslirp curl http://example.com/ ...

gateway$ DEBUG wgslirpy::router::serve_dns: DNS query example.com:0 DEBUG wgslirpy::router: Sending DNS reply

INFO wgslirpy::router: New NAT entry for Tcp { clientside: Endpoint { addr: Ipv4(Address([192, 168, 76, 1])), port: 48004 }, externalside: Endpoint { addr: Ipv4(Address([93, 184, 216, 34])), port: 80 } } DEBUG wgslirpy::router::servetcp: Connected to upstream TCP DEBUG wgslirpy::router::servetcp: Accepted the connection DEBUG wgslirpy::router::servetcp: EOF received from client DEBUG wgslirpy::router::servetcp: Shutdown finished DEBUG wgslirpy::router::servetcp: EOF DEBUG wgslirpy::router::servetcp: Client TCP socket no longer active DEBUG boringtun::noise::timers: KEEPALIVE(PERSISTENTKEEPALIVE) DEBUG wgslirpy::router: Finished serving Tcp { clientside: Endpoint { addr: Ipv4(Address([192, 168, 76, 1])), port: 48004 }, external_side: Endpoint { addr: Ipv4(Address([93, 184, 216, 34])), port: 80 } }

peer# ip netns exec testing-wgslirp dig +short github.com @8.8.8.8 140.82.112.3

gateway$ 01:26:14 INFO wgslirpy::router: New NAT entry for Udp ... 01:27:46 DEBUG wgslirpy::router::serve_udp: Timed out a UDP connection ```

Installation

Download a pre-built executable from Github releases or install from source code with cargo install --path . or cargo install wgslirpy.

CLI options

wgslirpy --help output

``` Usage: wgslirpy [-k ] [-f ] -K [-p ] [-a ] -b [-D ] [-P ] [--mtu ] [--tcp-buffer-size ] [--transmit-queue-capacity ] [-u

Expose internet access without root using Wireguard

Options: -k, --private-key main private key of this Wireguard node, base64-encoded -f, --private-key-file main private key of this Wireguard node (content of a specified file), base64-encoded -K, --peer-key peer's public key -p, --peer-endpoint address of the peer's UDP socket, where to send keepalives -a, --keepalive-interval keepalive interval, in seconds -b, --bind-ip-port where to bind our own UDP socket for Wireguard connection -D, --dns use this UDP socket address as a simple A/AAAA-only DNS server within Wireguard network -P, --pingable reply to ICMP pings on this single address within Wireguard network --mtu maximum transfer unit to use for TCP. Default is 1420. --tcp-buffer-size in-application socket TCP buffer size. Note that operating system socket buffer also applies. --transmit-queue-capacity nubmer of outgoing (to wireguard) packets to hold in a queue -u, --incoming-udp forward this host UDP port into Wireguard network. You need to specify triplet of socket addresses: host, source (optional) and dest. Host address is address to bind operating system socket to. source and dest addreses are used within Wireguard network. Example: -u 0.0.0.0:1234,10.0.2.1:1234,10.0.2.15:1234 -t, --incoming-tcp forward this host TCP port into Wireguard network. You need to specify triplet of socket addresses: host, source (optional) and dest. Host address is address to bind operating system socket to. source and dest addreses are used within Wireguard network. If source port is 0, roundrobin is used. Example: -t 0.0.0.0:1234,,10.0.2.15:1234 --help display usage information ```

See also