Exitway routes Chrome through a proxy on a VPS you control, so your browsing reaches the web from an address and a country you choose.
One person sets up the server. Everyone else installs a Chrome extension, pastes a token once, and presses Connect.
- An exit IP and country of your choosing, on a machine you rent and administer.
- Setup for a non-technical person that is one paste and one click.
- No third-party VPN account, no shared subscription, no client software from a company you have to trust.
- Per-person access. Each user gets their own token, which you can rotate or revoke in one command.
- No browsing history on the server. The access log records who connected and when, not where they went.
- Chrome 108 or later, or another Chromium browser built on it (Edge, Brave, Vivaldi). Firefox and Safari cannot run the extension.
- A Debian or Ubuntu VPS with root access.
- A DNS name pointing at that VPS, for example
proxy.example.com. - Inbound TCP on the proxy port (8443 by default), and inbound TCP 80 so Let's Encrypt can issue and renew the certificate. If nginx is already running on the box, certbot goes through it instead of binding port 80 itself.
On the VPS, as root:
git clone https://github.com/mill-master/exitway.git
cd exitway/server
sudo ./install.sh --domain proxy.example.com --location "Amsterdam" --email you@example.comThe installer prints what it is about to do and asks for confirmation. It installs squid-openssl and apache2-utils, gets a certificate from Let's Encrypt, writes the proxy configuration, installs the exitway command, opens the port in ufw if ufw is running, starts the proxy and checks the TLS handshake.
Options: --port <n> to listen somewhere other than 8443, --email <addr> for expiry warnings from Let's Encrypt, --yes to skip the confirmation prompt. The --location label is what users see in the extension and in the browser's login prompt.
Running the installer again is safe. It picks up a changed port or location and leaves existing accounts alone.
sudo exitway add aliceThis prints a token that starts with exitway_. The token carries the hostname, port, username and password in one pasteable string.
A token is a password. Send it to one person over a private channel, not to a group chat. If it leaks, run sudo exitway rotate alice.
Get the extension one of two ways:
- Download
exitway-<version>.zipfrom the Releases page and unzip it. - Or clone this repository and use the
extensionfolder directly.
Then:
- Open
chrome://extensions. - Turn on Developer mode, top right.
- Choose "Load unpacked" and select the unzipped folder (or
extension/from the clone). - The options page opens by itself the first time. Paste the token into the box and press "Add server".
- Click the Exitway icon in the toolbar and press Connect. The badge reads ON.
- Press "Check my IP". It should report the VPS's address and country.
Exitway is not in the Chrome Web Store. Load unpacked and the release zip are the two ways to install it. Chrome shows a "Disable developer mode extensions" warning on startup for unpacked extensions, which you can dismiss.
These commands run on the VPS.
| Command | What it does |
|---|---|
sudo exitway add <name> |
Creates an account and prints its token. Nobody currently browsing is interrupted. |
sudo exitway rotate <name> |
Issues a new token and kills the old one. Restarts the proxy, so connections drop for a second or two. |
sudo exitway revoke <name> |
Removes the account. Restarts the proxy, so access ends immediately. |
exitway list |
Accounts, and when each was last seen in the log. |
exitway status |
Service state, listening port, certificate expiry, account count. |
exitway audit |
The settings that decide what this server can see about browsing, and who has root on the box. |
add, rotate and revoke need root. list, status and audit run as any user, but read more when run with sudo, because the account file and the certificate are not world-readable.
Names may contain letters, digits, dots, underscores and hyphens.
Chrome is pointed at a single fixed proxy: your VPS, on the https proxy scheme. Everything Chrome sends to the proxy, including the destination hostnames and the account credentials, travels inside a TLS connection to the proxy and looks like ordinary HTTPS to anything on the path. Squid checks the credentials against a bcrypt password file, then opens the connection to the destination on your behalf.
flowchart LR
chrome["Chrome<br/>fixed proxy: proxy.example.com:8443"]
squid["Squid on your VPS<br/>TLS termination, Basic auth"]
site["Destination site"]
chrome -- "CONNECT site:443, inside TLS" --> squid
squid -- "TCP out, from the VPS's address" --> site
The page's own HTTPS runs end to end inside that tunnel, so the proxy relays bytes it cannot read.
docs/how-it-works.md has the detail: the token format, every proxy configuration decision and why it is there, what happens when things fail, and the threat model.
What the server records: time, client IP, account name, status code, bytes transferred, and HTTP method.
What it does not record: the destination host or URL. The access log accumulates no browsing history to leak, to hand over, or to read over someone's shoulder. Caching is off, so no page content lands on disk either. There is no TLS interception, so the contents of pages stay end to end encrypted between the browser and the site. Two things do still see hostnames: squid's error log, when a connection fails, and the VPS's DNS resolver, which is usually the provider's.
The proxy refuses connections to localhost, link-local and private ranges, and to the shared range cloud metadata services sit in, so a token holder cannot reach a database on the VPS's loopback, a device on its LAN, or the endpoint that hands out the hosting account's credentials. CONNECT is allowed to port 443 only, plain HTTP to port 80 only.
While connected, the extension sets Chrome's WebRTC policy to disable_non_proxied_udp, which stops WebRTC from opening its own paths and showing a site your real address. Disconnecting restores the setting.
Exitway fails closed. With a fixed proxy, Chrome does not fall back to a direct connection when the proxy is unreachable, so pages fail rather than quietly leaving from your own address.
It is not a VPN. Only Chrome's traffic is proxied. Other browsers, apps and system services are untouched.
Whoever holds root on the VPS can see the destination hostnames as they pass through, and can change the configuration to log them or to intercept TLS. exitway audit prints the settings that decide this, which is a spot-check rather than a guarantee. The full account is in docs/how-it-works.md.
To report a vulnerability, see SECURITY.md.
Server:
cd exitway/server
sudo ./uninstall.shThat removes the exitway command, the configuration, every account, the proxy's copy of the certificate and the renewal hook, and puts back the squid configuration that was there before, if there was one. Add --purge to remove the squid packages as well, and --yes to skip the prompt. The Let's Encrypt certificate is left alone, since it belongs to the domain and other services may use it, and so is the firewall rule for port 80 that certbot needs to renew it.
Extension: open chrome://extensions and remove it. Chrome drops the proxy settings the extension made, and browsing goes back to leaving directly.
The extension has no build step. The files under extension/ are what Chrome loads.
npm test # Node 22 or later, no dependencies
shellcheck server/*.sh server/exitway scripts/*.sh
scripts/package.sh # writes dist/exitway-<version>.zipCI runs the tests, a syntax check over every extension source file, and shellcheck over the shell scripts, on pushes to main and on pull requests. Pushing a tag that matches v* builds the zip and attaches it to a GitHub release.
MIT. See LICENSE.