proxyguard

package module
v0.0.0-...-39d201e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 25, 2024 License: MIT Imports: 16 Imported by: 1

README

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

  • Go (target: >= 1.19)

Building

Run: make

NOTE: You can build static binaries with CGO_ENABLED=0 make

Installing

Run: 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 development 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

Documentation

Index

Constants

View Source
const UpgradeProto = "UoTLV/1"

UpgradeProto is the protocol used in HTTP Upgrade UoTLV/1 is UDP over TCP Length Value version 1

Variables

View Source
var ErrReaderTimeout = errors.New("TCP reader timeout reached")

Functions

func Server

func Server(ctx context.Context, listen string, to string) error

Server creates a server that forwards TCP to UDP wgp is the WireGuard port tcpp is the TCP listening port to is the IP:PORT string

func UpdateLogger

func UpdateLogger(l Logger)

func Version

func Version() string

Version() gets the version in the following order: - Gets a release version if it detects it is a release - Gets the commit using debug info - Returns a default

Types

type Client

type Client struct {
	// Listen is the IP:PORT for the UDP listener
	Listen string

	// TCPSourcePort is the source port for the TCP connection
	TCPSourcePort int

	// Fwmark sets the SO_MARK to use
	// Set to 0 or negative to disable
	// This is only set on Linux
	Fwmark int

	// Ready is the callback that is called when the Proxy is connected to the peer
	// This only gets called on first connect of `Tunnel`
	Ready func()

	// SetupSocket is called when the socket is setting up
	// fd is the file descriptor of the socket
	// pips are the ips of the peer that the socket will attempt to connect to
	SetupSocket func(fd int, pips []string)
	// contains filtered or unexported fields
}

Client represents a ProxyGuard client

func (*Client) Tunnel

func (c *Client) Tunnel(ctx context.Context, peer string, pips []string) error

Tunnel tunnels a connection to peer `peer` The peer has IP addresses `pips`, if empty a DNS request is done

type Logger

type Logger interface {
	Log(_ string)
	Logf(_ string, _ ...interface{})
}

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL