Ctrl K
ComunidadGuías…

README.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# [vpn-switch](https://enk-ode.github.io/vpn-switch/)

A POSIX-shell-based VPN connection manager for FreeBSD and Linux. Handles
WireGuard and OpenVPN, automates firewall and DNS integration, and lets
you switch between configurations from any VPN provider with a single
command.

```sh
vpn-switch start privacy           # connect using the 'privacy' config
vpn-switch session save work       # name the live session
vpn-switch stop                    # tear it down
```

> **Platform support.** FreeBSD and Linux are the primary, tested platforms.
> FreeBSD ships an rc.d service and `resolvconf` / `local_unbound` DNS
> integration; Linux is supported for core connection and configuration
> management, with a systemd unit and an Alpine platform plugin. Alpine and
> OpenBSD are additionally verified as Tier-2 platforms (live walkthroughs in
> [EXTENDING.md](docs/EXTENDING.md)). The platform is auto-detected (`uname`
> plus `/etc/os-release`), and a new OS is added by dropping in a platform
> plugin. See [INSTALL.md](docs/INSTALL.md) for details.

---

## Why does this exist?

VPN provider documentation typically tells you: download a config file, run
`wg-quick up` or `openvpn`, manually patch firewall rules, manually update
DNS, repeat the inverse on disconnect. For a single config that's tolerable.
For dozens of configs across countries, protocols, and purposes, it isn't.

[vpn-switch](https://enk-ode.github.io/vpn-switch/) organises VPN configurations as a **filesystem database** — directories
group configurations by purpose, symlinks express defaults and named sessions,
and a small set of commands does the rest:

- **Switch between protocols and providers** without leaving the shell
- **Firewall + DNS handled automatically** via composable phase scripts
- **Session caching and resumption** — saved sessions reconnect instantly
- **Dry-run by default** for terminals — see the commands before they run
- **Per-function interpreter overrides** — log, validate, or replace any step
- **Pure POSIX `/bin/sh`** — no Python, no Go, no daemons, no dependencies

The same handful of commands covers one config or dozens across several
providers.

---

## Quick example

Source: <https://github.com/enk-ode/vpn-switch>. After install and `bootstrap`
(see the Documentation map below):

```sh
vpn-switch wireguard import ~/Downloads/wg-CH-12.conf       # ingest a config
vpn-switch wireguard add privacy wg-CH-12.conf switzerland  # group + alias it
vpn-switch start switzerland                                # connect
vpn-switch session list                                     # see what's running
vpn-switch session save work                                # name it
# ... use the VPN ...
vpn-switch stop                                             # disconnect
vpn-switch session start work                               # resume later
vpn-switch session switch home                              # or: stop + resume another, one step
```

---

## Documentation map

**Start here:**
- [INSTALL.md](docs/INSTALL.md) — System-wide installation (FreeBSD + Linux)
- [TUTORIAL_QUICKSTART.md](docs/TUTORIAL_QUICKSTART.md) — From install to first VPN connection
- [QUICK_REFERENCE.md](QUICK_REFERENCE.md) — One-page command cheatsheet

**Use the tool:**
- [TUTORIAL_SESSIONS.md](docs/TUTORIAL_SESSIONS.md) — Named sessions, save/resume
- [TUTORIAL_OPENVPN.md](docs/TUTORIAL_OPENVPN.md) — OpenVPN with a credentials file: no prompt, rotation, what travels
- [TUTORIAL_SUDO.md](docs/TUTORIAL_SUDO.md) — Per-function privilege escalation
- [TUTORIAL_MIGRATION.md](docs/TUTORIAL_MIGRATION.md) — export/import: the signed pair that moves the database
- [TUTORIAL_TROUBLESHOOTING.md](docs/TUTORIAL_TROUBLESHOOTING.md) — `vpn-switch validate` and beyond

**Understand the design:**
- [ARCHITECTURE.md](docs/ARCHITECTURE.md) — Combinator pattern, dispatch, interpreters
- [REQUIREMENTS.md](docs/REQUIREMENTS.md) — Technical requirements & constraints

**Debug & contribute:**
- [DEBUGGING_GUIDE.md](docs/DEBUGGING_GUIDE.md) — Three-pillar debugging methodology
- [EXTENDING.md](docs/EXTENDING.md) — Add a platform or protocol (Alpine + OpenBSD walkthroughs)
- [COMMIT_CHECKLIST.md](COMMIT_CHECKLIST.md) — Definition of done
- [CONTRIBUTING.md](CONTRIBUTING.md) — Issues, pull requests, and project stance
- [SECURITY.md](SECURITY.md) — How to report a vulnerability
- [CHANGELOG.md](CHANGELOG.md) — What's in each release

---

## Project status

Heading toward the first public release (1.0). Recent milestones:

- Unit, integration, architecture, and ownership test suites passing on
  FreeBSD and Linux (~860 tests, ~2350 assertions per platform)
- `vpn-switch sync` for upgrade-time DB refresh (phases + env + version)
  against source templates, and `vpn-switch version` for source/DB drift
- Cross-platform installer (FreeBSD + Linux, with an Alpine plugin) and an
  FHS-compliant layout

---

## Architecture at a glance

[vpn-switch](https://enk-ode.github.io/vpn-switch/) is built around a **combinator pattern**: every command is one
of three function types — terminal (`_`), combinator (`__`), or batch
combinator (`___`) — and each function outputs the next rewrite step
rather than executing side effects directly. Per-function "interpreters"
determine what happens to that output: execute it as shell (`sh`), display
it for inspection (`cat`), recurse it back through dispatch (`xargs sh -c`),
or anything else you set.

The result is a small, composable, deeply debuggable system. You can
inspect any rewrite step before execution by switching one variable:

```sh
vpn-switch setenv VPN_SWITCH_INTERPRETER_start cat
vpn-switch start privacy
# Shows what 'start' would dispatch to — no execution
```

For the full picture, see [ARCHITECTURE.md](docs/ARCHITECTURE.md).

**One process when it counts.** `vpn-switch-binary.sh <db> <command...>`
runs a command, or a whole batch (`batch <file>`), inside one process: the
anchors are functions, the emitted lines are calls of the engine's `main`,
the exit rules are the engine's. `vpn-switch-compile.sh` is the same file by
its other name and writes the script instead of running it;
`vpn-switch-walkthrough.sh` is the third name and shows the whole tree of a
command as text, checks answered against the database as it is, every act
under its anchor, nothing run. The engine itself lives in
`include/engine.sh`; `vpn-switch.sh` is the wrapper that loads it and the
modules.

---

## Phases & the patch step

Provider config files are usually written for Linux — a WireGuard file, for
example, embeds `PostUp`/`PostDown` DNS hooks that call Linux's `resolvconf`.
[vpn-switch](https://enk-ode.github.io/vpn-switch/) never runs the downloaded file as-is: at start time it **patches** a
session copy — stripping those Linux-specific hooks (DNS is handed to the DNS
phase instead) and, for OpenVPN, injecting the up/down scripts, daemon mode,
and the interface. One config then works on FreeBSD and Linux alike. Preview it
with `vpn-switch wireguard patch <config>` (or `openvpn patch`).

What the tunnel then does *around* itself — firewall, DNS, and more — is an
ordered list of **phases**:

```sh
VPN_SWITCH_PHASES_CONNECT    = firewall vpn dns     # disconnect runs the reverse
```

Each phase is generated from a swappable **backend** (firewall: `pf` / `ipfw` /
`iptables` / `none`; DNS: `resolvconf` / `unbound` / `djbdns` / `dnsmasq` /
`none`), chosen per phase via a `phase:backend` syntax — and you can drop in your
own backend script. That is what lets one tool serve a `pf`+`unbound` laptop and
an `iptables`+`dnsmasq` server without special-casing. Details:
`vpn-switch help phases`.

---

## Repository layout

```
vpn-switch/
├── vpn-switch.sh                  # Main script
├── vpn-switch-{unit,integration,architecture}-test.sh   # Test suites
├── GNUmakefile                    # Build/install/test
├── include/                       # Sourced shell modules (database.sh, session.sh, ...)
├── template/                      # Templates: env defaults, phase scripts, platform
│   ├── environment/               # VPN_SWITCH_* default values
│   ├── phase/                     # connect/disconnect/inspect phase scripts
│   └── platform/                  # OS-specific variables + Makefile plugins
├── scripts/                       # Build/dev tooling (generate-metadata, run-all-tests)
├── docs/                          # All documentation
└── README.md                      # You are here
```

---

## Shell completion

`gmake install` drops `completion/vpn-switch.bash` into
`share/bash-completion/completions/`, so Tab completes command words,
config and category names, sessions, environment variables, phases and
profiles. The shell side is a few lines: it asks
`vpn-switch complete <words...>`, which derives the candidates from the same
`#@help` corpus that renders `help` and the man page (placeholders map to
their value source through `@defcompletion` / `@completion`). Per user
without root: copy the file to
`~/.local/share/bash-completion/completions/vpn-switch`. Databases created
before this feature need `vpn-switch env sync` once for the display pin.

## Requirements

- POSIX `/bin/sh` (FreeBSD ash, dash, bash all work)
- WireGuard tools (`wireguard-tools` package) and/or OpenVPN (`openvpn` package)
- GNU `make` (called `gmake` on FreeBSD; default `make` on Linux)
- That's it. No language runtime, no daemon.

See [INSTALL.md](docs/INSTALL.md) for the per-OS package list and the
install procedure.

---

## License

BSD 2-Clause — see [LICENSE](LICENSE).

---

## Acknowledgements

Project developed by Dr. Johannes Brügmann with assistance from Claude
(Anthropic), 2024–2026.