Files
wg-connect/README.md
T
2026-06-23 18:41:23 +08:00

3.8 KiB

wg-connect

Bring a WireGuard tunnel up and down on BusyBox-based systems without wg-quick, systemd, or bash.

Requirements

  • wg - WireGuard userspace tool
  • ip - iproute2 or BusyBox ip
  • grep - BusyBox grep (with -E support)
  • POSIX /bin/sh

Root privileges are required (the script creates and configures network interfaces).

Installation

make install                      # to /usr/local
make install PREFIX=/usr          # to /usr
make install DESTDIR=/tmp/pkg     # for packaging

Or manually:

install -m 0755 wg-connect /usr/local/bin/wg-connect
install -m 0644 wg-connect.1 /usr/local/share/man/man1/wg-connect.1

Usage

wg-connect up <config>     # bring a tunnel up
wg-connect down [name]     # tear a tunnel down

up requires a config argument, resolved as follows:

Argument Resolves to
myvpn /etc/wireguard/myvpn.conf
myvpn.conf ./myvpn.conf, then /etc/wireguard/myvpn.conf
./foo.conf ./foo.conf (path with / - used as-is)
/any/path/c.conf /any/path/c.conf (absolute path)

The interface name is derived from the config file's basename (minus .conf). For example, wg-connect up myvpn creates interface myvpn, and wg-connect up /etc/wireguard/home.conf creates interface home.

down accepts an optional name to tear down a specific tunnel. Without a name it defaults to wg0.

Config format

Standard WireGuard [Interface] + [Peer] sections. wg-quick extensions (Address, DNS, etc.) are accepted. The script strips them before passing the config to wg setconf and handles them itself.

[Interface]
Address = 10.0.0.2/24
PrivateKey = oBKGh1W0UeO7R2aV5pLkdMn8Xq3TcFyRbzJwZsPvCg=
DNS = 1.1.1.1

[Peer]
PublicKey = xTIBA5rboUvnH4htjbDs6TFeFHS4k0mrKV4xJCzO0H8=
PresharedKey = /pUcv4j6DZ1UGm0PwR7aBr9Lk2sFdXq3OcVy5Jh8Tg=
Endpoint = 203.0.113.45:51820
AllowedIPs = 0.0.0.0/0

Multiple [Peer] sections are supported; AllowedIPs and Endpoint values are accumulated across all of them.

Note: if you run multiple tunnels, each must have a unique ListenPort (or omit it entirely). The script detects port conflicts before setting up the interface.

What it does

up

  1. Resolves the config path and derives the interface name.
  2. Checks for port conflicts with any existing WireGuard interface.
  3. Parses the config for Address, DNS, Endpoint, AllowedIPs, and ListenPort.
  4. Adds explicit routes for each peer endpoint through the current default gateway, so encrypted UDP packets are not caught in the tunnel's own routing.
  5. Creates the WireGuard interface and applies the config.
  6. Assigns the Address (appending /32 if no CIDR is given).
  7. Brings the interface up.
  8. Installs routes for each AllowedIPs entry. 0.0.0.0/0 replaces the default route.
  9. If DNS is set, backs up /etc/resolv.conf and writes the VPN nameserver.
  10. Saves state to /tmp/wg-connect.<iface>.state for teardown.

If any step fails, the trap handler rolls back everything created so far (interface, endpoint routes, state file).

down

  1. Reads /tmp/wg-connect.<name>.state.
  2. Restores the original /etc/resolv.conf.
  3. Removes the endpoint-specific routes.
  4. Deletes the interface (which also removes its addresses and routes).
  5. Restores the original default route if one was saved.
  6. Removes the state file.

If the state file is missing but the interface still exists, down falls back to cleaning up the leftover interface.

Limitations

  • IPv6 addresses and routes are skipped (BusyBox ip may lack -6 support).
  • DNS supports a single nameserver only.
  • PostUp / PostDown / PreUp / PreDown hooks are not executed.
  • No firewall rules are added. If you need a kill switch, configure iptables separately.