ProxyGuard
Proxy UDP connections over HTTP(s). The main use case is to proxy WireGuard packets.
It does this by doing a HTTP upgrade request similar to how websockets work.
This means we can tunnel the protocol behind a reverse proxy.
Dependencies
Building
Run: make
NOTE: You can build static binaries with CGO_ENABLED=0 make
Installing
Run:
$ sudo make install
This will install the daemons under /usr/local
and add the systemd
service files. Do not forget to run systemctl daemon-reload
. After that you
can start the proxyguard-server
and proxyguard-client
services.
To configure them, use e.g. systemctl edit proxyguard-server
and override the
variables you see there with your own values as needed, for example if
WireGuard is listening on port 443, you can add the following:
[Service]
Environment=TO=127.0.0.1:443
DEB/RPM packages
Currently there are DEB/RPM packages available in eduVPN's server repository, follow the eduVPN docs to add the repo.
And then install ProxyGuard using: sudo apt -y install proxyguard-client
or sudo dnf -y install proxyguard-client
Running
This tool is focused on a client-server model. This proxy thus needs to run for every client and for a server. The server mode accepts multiple clients.
Client example
This example listens on local UDP port 1337 and forwards TCP packets (with a HTTP Upgrade handshake) to vpn.example.com
proxyguard-client --listen 127.0.0.1:1337 --to http://vpn.example.com
NOTE: If you test the client on Linux, you might also need to add --fwmark 51820 (or some other number that the WG connection configures) to mark that the packets going out of this proxy are encrypted, preventing a routing loop. 51820 is the default for WireGuard. Note that this needs root.
NOTE: The default HTTP client source port is the same as the UDP listen port, 1337 in this case. To change this, pass --tcpport. You can set it to 0 to automatically pick an available TCP source port.
The received packets from the server (in this case vpn.example.com
) are forwarded back to the address of the first received UDP packet. So if the proxy receives an UDP packet from port x first, it will remember this as the destination for received packets. This is so that WireGuard can use a dynamic port.
To then use this with WireGuard, you need to change the endpoint in the WireGuard config:
[Peer]
PublicKey = pubkeyhere
AllowedIPs = 0.0.0.0/0, ::0
Endpoint = 127.0.0.1:1337
Server example
This example starts a HTTP server on TCP port 1337 and forwards UDP packets to localhost 51820, the WireGuard port.
proxyguard-server --listen 0.0.0.0:1337 --to 127.0.0.1:51820
Deployment
For details on deployment, see here.
Technical docs
For technical docs, see here.
Acknowledgements & Thanks
The following projects gave me an idea how I could implement this best, most notably how to do the UDP <-> TCP conversion with a custom header. This project started with a UDP to TCP approach, but later moved to HTTP for use behind a reverse proxy and improved obfuscation.
License
MIT