aboutsummaryrefslogtreecommitdiff
# 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 ```sh make install # to /usr/local make install PREFIX=/usr # to /usr make install DESTDIR=/tmp/pkg # for packaging ``` Or manually: ```sh 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 ```sh wg-connect up # 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. ```ini [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..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..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.