Skip to content

Zhegl/lift-proxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

lift-proxy

UDP tunnel that wraps WireGuard traffic inside BACnet/IP packets (port 47808).

Disclaimer

This project is for educational purposes only. The code may contain bugs and security vulnerabilities — use at your own risk. The author takes no responsibility for any damage, data loss, or legal consequences arising from its use.

lift-proxy provides no encryption or authentication of its own. It is a plain, unauthenticated UDP transport. All security — confidentiality, integrity, authentication — is handled entirely by WireGuard. Do not use lift-proxy to tunnel anything other than WireGuard (or another encrypted protocol) without understanding the implications.

How it works

[WireGuard client] <-> [lift-proxy client] <--(BACnet/IP UDP)--> [lift-proxy server] <-> [WireGuard server]

WireGuard packets are encapsulated in BACnet/IP BVLC frames, which look like industrial automation traffic to a DPI firewall.

Build

cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)

Binary: build/lift-proxy

Deployment

Server

On the VPS (runs alongside WireGuard):

./lift-proxy \
  --mode=server \
  --listen=0.0.0.0:47808 \
  --forward=127.0.0.1:51820
  • --listen — port that receives BACnet packets from clients
  • --forward — local WireGuard UDP port

Client

On the client machine:

./lift-proxy \
  --mode=client \
  --listen=127.0.0.1:51820 \
  --forward=SERVER_IP:47808 \
  --queue_size=16
  • --listen — local port WireGuard is configured to use as endpoint
  • --forward — server IP and BACnet port
  • --queue_size — send queue depth (see tuning section)

WireGuard configuration

Server (/etc/wireguard/wg0.conf)

[Interface]
PrivateKey = <server private key>
Address = 10.10.0.1/24
ListenPort = 51820

[Peer]
PublicKey = <client public key>
AllowedIPs = 10.10.0.2/32

Client

[Interface]
PrivateKey = <client private key>
Address = 10.10.0.2/24
DNS = 1.1.1.1
MTU = 1414

[Peer]
PublicKey = <server public key>
Endpoint = 127.0.0.1:51820
AllowedIPs = <0.0.0.0/0 split excluding your server IP>
PersistentKeepalive = 25

The Endpoint points to localhost because lift-proxy client listens there and forwards to the real server.

AllowedIPs must route all traffic through the tunnel except the server's own IP (otherwise tunnel packets would loop back into the tunnel). WireGuard doesn't support exclusions natively, so you need to split 0.0.0.0/0 into CIDR blocks that cover everything except your server IP. Use any online "exclude IP from CIDR" calculator (e.g. search "wireguard exclude ip allowed ips calculator").

Tuning

MTU

The correct MTU for the WireGuard interface is:

MTU = physical_iface_MTU - 20 (outer IP) - 8 (outer UDP) - 10 (BACnet header) - 48 (WireGuard overhead)

For a standard 1500 MTU network: 1414.

If MTU is too high, large packets (TLS handshakes, HTTP responses) get fragmented and may be dropped by the network, causing:

  • TLS handshake timeouts in browsers
  • Sites loading via curl but not in browser
  • GitHub and other HTTPS-heavy sites timing out

Send queue and bufferbloat

The --queue_size flag controls how many packets can queue up before older ones are dropped.

Default is 4096, which causes severe bufferbloat on slow upload links — ping spikes to 500-700ms during uploads because the queue holds several seconds of backlog.

Recommended values:

  • 16 — low latency, some packet loss under heavy load (TCP self-throttles quickly)
  • 64 — balanced
  • 4096 — default, only useful on very fast symmetric links

For typical consumer connections (10-50 Mbit/s upload), use --queue_size=16.

Persistent keepalive

Without PersistentKeepalive, WireGuard lets the session go idle and must re-handshake on the next packet. This causes the first ping after a long idle period to take 1+ seconds.

Set PersistentKeepalive = 25 in the client's [Peer] section.

About

tunnel over BACNET/IP

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors