Antizapret created to redirect only blocked domains to VPN tunnel. Its called split tunneling. This repo is based on idea from original AntiZapret LXD image
- Support and discussions group
- Features
- How it works
- Installation
- Documentation
- Credits
https://t.me/antizapret_support
- Modular design. External and high quality opensource modules/containers are used as builing blocks of our system.
- User friendly web panels for administration of VPN's and DNS.
- Multiple VPN transports: Wireguard, Amnezia Wireguard, OpenVPN
- AdguardHome as main DNS resolver and blocked domains manager
- Multi-Server Architecture to bypass services geo restrictions. Different domains use different servers as exit nodes.
- Firewall to protect from port scanning
- Support for kernel modules for OpenVPN and Amnezia Wireguard to decrease CPU usage.
- SOCKS5 proxy (Dante) for per-application routing through local or world exit nodes
- List of blocked domains downloaded from open registry.
- List parsed and rules for dns resolver (adguardhome) created.
- Adguardhome resend requests for blocked domains to python script dnsmap.py.
- Python script: a) resolve real address for domain b) create fake address from 14.16.0.0/14 subnet c) create iptables rule to forward all packets from fake ip to real ip.
- Fake IP is sent in DNS response to client
- VPN tunnels configured with split tunneling. Only traffic to 14.16.0.0/14 subnet is routed through VPN.
Important
Commands must be run as root. Otherwise, config files will have inconsistent rights, and some containers will reboot infinitely.
Recommended to use server located in western countries. Some sites will block users from other countries.
- Install Docker Engine:
curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh
- Clone repository and start container:
git clone https://github.com/xtrime-ru/antizapret-vpn-docker.git antizapret cd antizapret git checkout v6 - Create docker-compose.override.yml with services you need. Minimal example with only wireguard:
services:
adguard:
environment:
- ADGUARDHOME_PASSWORD=somestrongpassword
wireguard:
environment:
- WIREGUARD_PASSWORD=somestrongpassword
extends:
file: services/wireguard/docker-compose.yml
service: wireguardFind full example in docker-compose.override.sample.yml
- Start services:
docker compose up -d
docker system prune -fVersion 5 and 6 comes with ability to forward traffic to different exit nodes for different domains. For example, YouTube works best if exit node is close to client and other services require foreign IP to work. Docker swarm is used to build unified network between containers.
Its recommended to use local server as manager/primary node for VPN's, DNS and az-local containers. Foreign server – as secondary/worker node for az-world container.
Most of the domains will be proxied through local server for maximum speed and performance. Some of the sites, which use geoip to block users, will be proxied through foreign server.
- Repeat steps 0 and 1 from single server installation on both servers:
- Install docker
- Checkout project in same location on both servers.
- [Primary] Create docker-compose.override.yml on primary node and define which services you need. See step 2 from single server installation.
- [Primary] Change hostnames of servers to az-local and az-world for ease of use:
hostnamectl set-hostname az-local - [Secondary] Change hostnames of servers to az-local and az-world for ease of use:
hostnamectl set-hostname az-world - [Optionally] hub.docker.com can be unreachable on local hostings. Proxy can be used. See instructions: https://dockerhub.timeweb.cloud
Alternatively images can be build locally on both servers:
docker compose build - [Primary]:
docker swarm init --advertise-addr <PRIMARY_SERVER_PUBLIC_IP_ADDRESS> - [Secondary]: Copy command from results and run it on secondary node:
docker swarm join --token <TOKEN> <MANAGER_IP_ADDRESS>:<PORT> - [Primary]: Inspect swarm
docker node lsID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION 6dzagr08r8d2iidkcumjjz3q7 * az-local Ready Active Leader 29.0.1 vspy2m6w4tf7uv4ywgdnzttvr az-world Ready Active 29.0.1 - [Primary] Add labels for nodes
docker node update --label-add location=local az-local && docker node update --label-add location=world az-world - [Primary]: start swarm
docker compose config | docker run --pull always --rm -i xtrime/antizapret-vpn:6 compose2swarm | docker stack deploy --prune -c - antizapret
Most providers now block vpn connections to foreign IPs. Obfuscation in Amnezia or OpenVpn not always fix the issue. For stable vpn operation you can try to connect to VPS inside your country and then proxy traffic to foreign server.
There are two ways:
- [Recommended] Installation in docker swarm mode
- Proxy all traffic via local proxy. See below.
Example of startup script. Replace <SERVER_IP> with IP address of your server and run it on fresh VPS (ubuntu 24.04 is recommended):
#!/bin/sh
# Fill with your foreign server ip
export VPN_IP=<SERVER_IP>
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.d/99-sysctl.conf
sysctl -w net.ipv4.ip_forward=1
# DNAT rules
iptables -t nat -A PREROUTING -p tcp ! --dport 22 -j DNAT --to-destination "$VPN_IP"
iptables -t nat -A PREROUTING -p udp ! --dport 22 -j DNAT --to-destination "$VPN_IP"
# MASQUERADE rules
iptables -t nat -A POSTROUTING -p tcp -d "$VPN_IP" -j MASQUERADE
iptables -t nat -A POSTROUTING -p udp -d "$VPN_IP" -j MASQUERADE
echo iptables-persistent iptables-persistent/autosave_v4 boolean true | sudo debconf-set-selections
echo iptables-persistent iptables-persistent/autosave_v6 boolean false | sudo debconf-set-selections
apt install -y iptables-persistent
- Make sure Secure DNS is disabled in your browser settings. In chrome: Navigate to Settings > Privacy and security > Security, scroll to the "Advanced" section, and toggle off "Use secure DNS"
- Install DKMS modules for openvpn and/or amnezia wireguard (if you use them):
By default, all container can be accessed via https. For certificated management separate https container is used.
If you did not provide domain and email in its env it will generate self-signed certificates
- dashboard: https://%your-server-ip%:443
- adguard: https://%your-server-ip%:1443
- filebrowser: https://%your-server-ip%:2443
- openvpn: https://%your-server-ip%:3443
- wireguard: https://%your-server-ip%:4443
- wireguard-amnezia: https://%your-server-ip%:5443
When you connected to VPN, you can access containers without exposing ports to internet:
- http://adguard.antizapret:3000
- http://dashboard.antizapret:80
- http://wireguard-amnezia.antizapret:51821
- http://wireguard.antizapret:51821
- http://openvpn-ui.antizapret:8080
- http://filebrowser.antizapret:80
By default, containers don't expose web panels to internet. All web panels are proxied via https container.
If you want to expose http to internet, add port forwarding to docker-compose.override.yml.
Example:
services:
adguard:
#...
ports:
- "3000:3000/tcp"List of default ports:
- adguard: http://%your-server-ip%:3000
- dashboard: http://%your-server-ip%:80
- wireguard-amnezia: http://%your-server-ip%:51821
- wireguard: http://%your-server-ip%:51821
- openvpn-ui: http://%your-server-ip%:8080
- filebrowser: http://%your-server-ip%:80
Some containers have same ports. So you need to choose unique external port in docker-compose.override.yml.
- Single instance
git pull --rebase docker compose down --remove-orphans docker compose up -d --remove-orphans docker system prune -af
- Swarm mode:
git pull --rebase docker pull xtrime/antizapret-vpn:6 docker compose config | docker run --pull always --rm -i xtrime/antizapret-vpn:6 compose2swarm | docker stack deploy --prune -c - antizapret docker system prune -af
- Upgrade containers:
- Docker Compose mode (single server):
docker compose down --remove-orphans git fetch && git checkout v6 && git pull --rebase docker compose down --remove-orphans docker compose up -d --remove-orphans docker system prune -af
- Swarm mode:
- master node:
docker stack rm antizapret && sleep 10 git fetch && git checkout v6 && git pull --rebase docker compose config | docker run --pull always --rm -i xtrime/antizapret-vpn:6 compose2swarm | docker stack deploy --prune -c - antizapret docker system prune -af
- worker nodes:
git fetch && git checkout v6 && git pull --rebase
- Update clients:
- Wireguard/Amnezia
- Check if your password is longer than 12 symbols. Update if needed in docker-compose.override.yml
- Download new client configs, or add
14.16.0.0/14to AllowedIps manually in old configs.
- OpenVPN
- Click save at openvpn-ui server config page: http://openvpn-ui.antizapret:8080/ov/config/ and then restart openvpn server.
- Install new dkms module on host:
apt remove openvpn-dkms-dco+ https://github.com/xtrime-ru/antizapret-vpn-docker/blob/v6/README.md?tab=readme-ov-file#enable-openvpn-data-channel-offload-dco
- Socks Replace it with proxy container and rename ENV variables. See example: https://github.com/xtrime-ru/antizapret-vpn-docker/blob/v6/docker-compose.override.sample.yml#L63-L93 Make sure you use strong password, because now HTTPS proxy accessible from internet.
- Wireguard/Amnezia
Remove all settings, vpn configs and return initial state of service:
docker stack rm antizapret || docker compose down --remove-orphans
rm -rf config/*
git restore config-
How to get VPN configs?
- OVPN:
- https://%your-server-ip%:3443/certificates
- Create Certificate
- Enter Any Name and leave all other fields as is
- Click "Create". New certificate will appear in the list.
- Click on certificate name in the list to download it.
- Wireguard or Amnezia:
- Go to https://%your-server-ip%:4443 or https://%your-server-ip%:5443
- Click "New"
- Enter any name.
- Create client
- Click download button in the list.
- QR Codes dont work for Amnezia Wireguard, because config is too big for QR code
- OVPN:
-
Which Amnezia Wireguard client to use? A recommended client for Amnezia Wireguard is AmneziaWG:
-
Why don't OpenVPN client connect to server? Most providers block openvpn protocol, especially to foreign IPs. The symptoms are: client connects, but after few transferred bytes server stops responding and connection is terminated.
- By default, an openvpn container uses light obfuscation of UDP packets.
It works on most clients (including routers) but still can be blocked by providers.
See OBFUSCATE_TYPE env.
Try to change it from default1(light) to2(strong) or0(off). - Use cascade connection or swarm mode cascade
- By default, an openvpn container uses light obfuscation of UDP packets.
-
Why can VPN connection be slow and have a lot of dropped packets?
-
First, use reproducible test to detect issues: Test speed with iperf3
-
Check if CPU on your hosting is not overloaded during iperf test.
-
Ensure kernel modules for your VPN are installed and working: OVPN DCO, Amnezia Wireguard Kernel Extension.
-
Some inexpensive hostings have very slow CPUs, so even with all kernel modules installed, connection speed will not exceed 100 Mbit/s.
-
Most routers have slow CPUs and provide only 30-60 Mbit/s via openvpn. Try to use Wireguard or Amnezia Wireguard if router supports it or update router to newer model.
-
In rare cases low MTU between client and server can cause packet fragmentation. First, check if your VPN connection has issues with default MTU.
- MacOs:
ping -D -s 1420 google.com - Linux:
ping -M -s 1420 google.com - Windows:
ping google.com -f -l 1420
If this command returns errors, then keep lowering the value until it works. Then lower MTU in VPN settings.
- Wireguard/Amezia:
MTU Must be lower on both server and client.
- Go to http://wireguard.antizapret:51821 or http://wireguard-amnezia.antizapret:51821 and click on client config icon.
- Lower MTU to 1200 and save. MTU is client-specific.
- Download and apply new config to your client.
- Test speed with iperf3
- OpenVPN:
- Go to http://openvpn-ui.antizapret:8080/ov/config and add
link-mtu 1200to your server config. - Save Config and restart server.
- Add
link-mtu 1200to your client.conf
- Go to http://openvpn-ui.antizapret:8080/ov/config and add
- MacOs:
-
If nothing helps, try another hosting and/or cascade
-
-
How to debug issues with VPN?
- Check if the VPN connection is established and the DNS server is working:
> nslookup youtube.com Server: 14.16.0.1 Address: 14.16.0.1#53 Non-authoritative answer: Name: youtube.com Address: 14.16.13.209 - Check if browser dont use DoH/Secure DNS.
- Check DIST filters have loaded and have non 0 rule counters: http://adguard.antizapret:3000/#filters
- Check DNS resolution steps: http://adguard.antizapret:3000/#logs?response_status=all&search=youtube.com Each domain resolved via 2–4 DNS requests. See: DNS resolving algorithm
- Check if the VPN connection is established and the DNS server is working:
- DNS Request arrives into AdGuardHome
- Adguard check it with blacklist rules. If domain in blacklist - return 0.0.0.0 and client not able to access domain.
- Adguard Send DNS request to CoreDNS service.
- CoreDNS Send DNS request to internal dnsmap.py server (antizapret container) and dnsmap.py sends request back to adguard
- Adguard receives requests one more time, but now applies rules with
$client=az-localand real upstream server client (8.8.8.8 by default) - If domain in whitelist - adguard will resolve its address and return to dnsmap.py
- If domain not in whitelist adguard return SERVFAIL
- dnsmap.py send response to adguard:
- If it is valid IP, then replaces it with "internal" IP from
14.16.0.0/15subnet, add masquerade to iptables and return internal ip to adguard - If is is SERVFAIL it sends this response to client.
- If it is valid IP, then replaces it with "internal" IP from
- If CoreDNS receives SERVFAIL it retries request and send it directly to Adguard. In this case rules with
$client=az-localdo not applied and request processed normally.
Why so complicated?
- Windows and some other clients do not retry to Fallback DNS, even if SERVFAIL received. So we added CoreDNS for that.
- Adguard don't allow to redefine upstream in blacklist/whitelist rules. But this rules have regex support and updated automatically, so we want to use them. So multiple requests from different clients are made internally.
- Adguard allows different upstreams for different clients. So we can use different DNS for blocked and non blocked domains.
Example:
We requested youtube.com, which should be routed via az-local node.
- DNS request from client to Adguard. Routed to coredns. Response will appear after all following requests are processed.
Status: Processed DNS server: coredns:53 Elapsed: 91 ms Served from cache: False Response code: NOERROR Response: A: 14.16.13.209 (ttl=300) A: 14.16.13.207 (ttl=300) A: 14.16.13.206 (ttl=300) A: 14.16.13.208 (ttl=300) - DNS request from coredns to az-world. And az-world request to Adguard:
SERFAIL response means that this domains not routed via az-world.
Status: Rewritten Elapsed: 0.10 ms Response code: SERVFAIL Rule(s): ||*^$dnsrewrite=SERVFAIL,client=az-world Custom filtering rules - DNS request from coredns to az-local. And az-local request to Adguard:
In this case domain must be served via az-local and excluded from blacklist for az-local client. Adguard cant find this domain in blacklist for az-local and and return real addresses to az-local client.
Status: Processed DNS server: 149.112.112.11:53 Elapsed: 50 ms Response code: NOERROR Response A: 173.194.221.190 (ttl=300) A: 173.194.221.91 (ttl=300) A: 173.194.221.136 (ttl=300) A: 173.194.221.93 (ttl=300) - az-local container adds masquerade to iptables and return internal ip to coredns.
- coredns send response to adguard and adguard caches it and return to client.
There are two ways of adding domains. Via custom rules and via black lists.
Open adguard panel: http://adguard.antizapret:3000/#custom_rules Rules/syntaxes: https://adguard-dns.io/kb/general/dns-filtering-syntax/#basic-examples
By default, adguard rewrite all requests with SERVFAIL. This is a trick to make client retry DNS request to second, local DNS server.
Rules with the dnsrewrite response modifier have higher priority than other rules in AdGuard Home and AdGuard DNS.
To override default rule custom rules must have $dnsrewrite modifier.
To support default adguard filters default SERVFAIL rule applied only to internal requests from client=az-local and client=az-world
Examples:
@@||subdomain.host.com^$dnsrewrite,client=az-local
@@||*.host.com^$dnsrewrite,client=az-local
@@||host.com^$dnsrewrite,client=az-world
@@||de^$dnsrewrite,client=az-world
@@/some_.*_regex/$dnsrewrite,client=az-local
Also you can add any urls to blocklist. http://adguard.antizapret:3000/#dns_blocklist Need to use adapter, to parse and adapt list in different formats.
- Add domains for local exit node:
http://az-local.antizapret/list/?url=<ANY_URL> - Add domains for world exit node
http://az-world.antizapret/list/?url=<ANY_URL>Supported formats: simple list of domains, adguard format, hosts format, json array of domains, regex list.
Options for adapter:
url- download list from urlfile- read local file. Used for include-host-{custom,dist}.txtfilter_custom=1- filter lists with rules from exclude-hosts-custom.txt.filter_dist=0- filter lists with rules from exclude-hosts-dist.txtformat=list- 'list' or 'json'. Detected automatically.client=az-local- name of client to add to rules. Detected automatically.allow=1- disable this option, to block domains from list for this exit node.raw=0- dont modify rulessuffix=1- add "$dnsrewrite,client=xxx" to rulesdnsrewrite=SERVFAIL- set custom dnsrewrite value
Add ips and subnets to ./config/antizapret/custom/include-ips-custom.txt.
Containers periodically check changes in config folder (every 5-10 seconds) and restart/update after any change.
Trigger update manually: docker exec $(docker ps -q --filter=name=az | head -n1) doall
AntiZapret uses DNS-based split tunneling, which works only for domain-based connections. If an application connects directly by IP address, DNS interception does not work and traffic is not routed through the VPN tunnel.
proxy service is based on 3proxy container
It's a solution for per-application routing.
- Connect to VPN (OpenVPN, WireGuard or Amnezia WireGuard)
- Configure your application to use SOCKS5 or HTTP/HTTPS proxy via proxy settings or tools like AntizapretSOCKS5 (Windows), ProxyBridge, Proxifier or proxy settings in a web browser.
- All traffic from that application (including direct IP connections) will exit through the selected server node
Two proxy containers are available:
proxy-local.antizapret— traffic exits through the local server- SOCKS5 port:
8118 - HTTP port:
8180 - HTTPS (local) via
httpscontainer:https://%your_ip%:8143
- SOCKS5 port:
proxy-world.antizapret— traffic exits through the world server- SOCKS5 port:
8118 - HTTP port:
8180 - HTTPS (world) via
httpscontainer:https://%your_ip%:8243
- SOCKS5 port:
Authentication: Basic (SOCKS5/HTTP/HTTPS) configured via environment variables. Authentication is required because the HTTPS proxy is accessible from the internet.
| Scenario | DNS routing | Proxy |
|---|---|---|
| Application connects by domain | ✅ Works | ✅ Works |
| Application connects by IP | ❌ Not routed | ✅ Works |
| Large number of IPs to route | ❌ OpenVPN push routes limit | ✅ No limit |
| Per-application exit node selection | ❌ | ✅ Choose local or world per app |
Add proxy services to docker-compose.override.yml:
proxy-local:
hostname: proxy-local.antizapret
extends:
file: services/proxy/compose.yml
service: proxy
environment:
- PROXY_LOGIN=admin
- PROXY_PASSWORD=password
deploy:
mode: replicated
replicas: 1
endpoint_mode: dnsrr
placement:
constraints: [ node.labels.location == local ]
proxy-world:
hostname: proxy-world.antizapret
extends:
file: services/proxy/compose.yml
service: proxy
environment:
- PROXY_LOGIN=admin
- PROXY_PASSWORD=password
deploy:
mode: replicated
replicas: 1
endpoint_mode: dnsrr
placement:
constraints: [ node.labels.location == world ]Note:
proxy-worldrequires Docker Swarm mode with two nodes. On a single server onlyproxy-localwill work.
- Connect to VPN
- Configure SOCKS5 or HTTP/HTTPS proxy in your application or browser:
- Host:
proxy-local.antizapretorproxy-world.antizapret - SOCKS5 Port:
1080 - HTTP/HTTPS Port:
3128 - Username: value of
PROXY_LOGIN - Password: value of
PROXY_PASSWORD
- Host:
You can define these variables in docker-compose.override.yml file for your needs:
Consists of two containers: az-local and az-world. This is VPN exit nodes.
DNS=adguard- Upstream DNS for resolving blocked sites (adguard by default)AZ_SUBNET=14.16.0.0/14Subnet for virtual addresses for blocked hosts.ROUTES- list of VPN containers and their virtual addresses. Used for iperf3 server.DOALL_DISABLED=- skip run on az-world node.
ROUTES- list of VPN containers and their virtual addresses. Used for unique client addresses in adguard logsADGUARDHOME_PORT=3000ADGUARDHOME_USERNAME=adminADGUARDHOME_PASSWORD=ADGUARDHOME_PASSWORD_HASH=- hashed password, taken from the AdGuardHome.yaml file after the first run usingADGUARDHOME_PASSWORD. Dollar sign$in hash must be escaped with another dollar sign:$$
- None
FILEBROWSER_PORT=adminFILEBROWSER_PASSWORD=password
PROXY_DOMAIN=- create letsencrypt https certificate for domain. If not set host ip is used for self-signed certificate.PROXY_EMAIL=- email for letsecnrypt certificate.
ROUTESOBFUSCATE_TYPE=1- custom obfuscation level of openvpn protocol.- 0 - disable. Regular openvpn client mode, supported by all clients.
- 1 - light obfuscation. Works with microtic and old keenetic routers
- 2 - strong obfuscation. Works with most of the clients: openvpn official gui client, asus routers, new keenetic routers, openwrt routers.
AZ_SUBNET=14.16.0.0/14- subnet for virtual blocked ips.
OPENVPN_ADMIN_USERNAME=- replace default username with your usernameOPENVPN_ADMIN_PASSWORD=- replace default password with your passwordOPENVPN_EXTERNAL_IP- external ip of your server, by default detected automaticallyOPENVPN_DNS=14.16.0.1- DNS address for clients. Must be inANTIZAPRET_SUBNETOPENVPN_LOCAL_IP_RANGE=10.1.165.0- subnet for ovpn clients. Subnet can be viewed in adguard journal or in ovpn-ui panel
ROUTESWIREGUARD_PASSWORD=- password for admin panel (used during initial setup only, change password via web UI afterwards)WIREGUARD_USERNAME=admin- username for admin panel (used during initial setup only)AZ_SUBNET=14.16.0.0/14- subnet for virtual blocked ips.WG_DEFAULT_DNS=14.16.0.1- DNS address for clients. Must be inANTIZAPRET_SUBNETWG_PERSISTENT_KEEPALIVE=25PORT=51821- admin panel portINSECURE=true- allow HTTP access to admin panelDISABLE_IPV6=true- disable IPv6 supportWG_PORT=51820- wireguard server portEXPERIMENTAL_AWG=true- enable AmneziaWG support (wireguard-amnezia only)OVERRIDE_AUTO_AWG=awg- environment variable to force the tunnel type:awgto always use AmneziaWG,wgto always use standard WireGuard; by default it’s unset and automatic detection is used, useful to override auto-selection and lock the mode.BGP_ENABLE=false- start bird BGP server. Server will push routes to clients (some routers). Clients will receive route updates without updating wg/awg config.
SOCKS_USERNAME- username for SOCKS5 authentication (omit to disable authentication)SOCKS_PASSWORD- password for SOCKS5 authentication (omit to disable authentication)
PROXY_LOGIN- username for HTTP authentication (omitting disable authentication)PROXY_PASSWORD- password for HTTP authentication (omitting disable authentication)PROXY_PORT=8180- HTTP port to listenSOCKS_PORT=8118- SOCKS5 port to listenEXTRA_ACCOUNTS- Additional login:password pairs. Example:login:password;login2:password2EXTRA_CONFIG- Raw 3proxy config lines injected before proxy/socks directives (empty by default)
Adguard uses Google DNS and Quad9 DNS to resolve unblocked domains. This upstreams support ECS requests (more info below). Cloudflare DNS do not support ECS and is not recommended for use.
Source code: Adguard upstream DNS
After container is started working copy is located here: ./config/adguard/conf/upstream_dns_file_basis
Some domains can resolve differently, depending on subnet (geoip) of client. In this case using of DNS located on remote server will break some services. ECS allow to provide client IP in DNS requests to upstream server and get correct results. Its enabled by default in Adguard and client ip is pointed to Moscow (Yandex Subnet).
If you located in other region, you need to replace 77.88.8.8 with your real ip address on this page http://your-server-ip:3000/#dns
https://github.com/d3vilh/openvpn-ui?tab=readme-ov-file#generating-ovpn-client-profiles
- go to
http://%your_ip%:8080/certificates - click "create certificate"
- enter unique name. Leave all other fields empty
- click create
- click on certificate name in list to download ovpn file.
OpenVPN Data Channel Offload (DCO) provides performance improvements by moving the data channel handling to the kernel space, where it can be handled more efficiently and with multi-threading. tl;dr it increases speed and reduces CPU usage on a server.
Kernel extensions can be installed only on a host machine, not in a container.
sudo rm -f /etc/apt/sources.list.d/openvpn.list
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://swupdate.openvpn.net/repos/repo-public.gpg | sudo gpg --dearmor --yes -o /etc/apt/keyrings/openvpn-repo-public.gpg
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/openvpn-repo-public.gpg] http://build.openvpn.net/debian/openvpn/release/2.7 noble main" | sudo tee /etc/apt/sources.list.d/openvpn-aptrepo.list > /dev/null
sudo apt update
sudo apt install -y ovpn-dkmssudo rm -f /etc/apt/sources.list.d/openvpn.list
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://swupdate.openvpn.net/repos/repo-public.gpg | sudo gpg --dearmor --yes -o /etc/apt/keyrings/openvpn-repo-public.gpg
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/openvpn-repo-public.gpg] http://build.openvpn.net/debian/openvpn/release/2.7 jammy main" | sudo tee /etc/apt/sources.list.d/openvpn-aptrepo.list > /dev/null
sudo apt update
sudo apt install -y ovpn-dkmssudo rm -f /etc/apt/sources.list.d/openvpn.list
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://swupdate.openvpn.net/repos/repo-public.gpg | sudo gpg --dearmor --yes -o /etc/apt/keyrings/openvpn-repo-public.gpg
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/openvpn-repo-public.gpg] http://build.openvpn.net/debian/openvpn/release/2.7 focal main" | sudo tee /etc/apt/sources.list.d/openvpn-aptrepo.list > /dev/null
sudo apt update
sudo apt install -y ovpn-dkmsIf your clients do not have GCM ciphers support you can use legacy CBC ciphers. DCO is incompatible with legacy ciphers and will be disabled. This is also increase CPU load.
https://github.com/amnezia-vpn/amneziawg-linux-kernel-module?tab=readme-ov-file#ubuntu
sudo add-apt-repository ppa:amnezia/ppasudo apt install -y amneziawg- restart server or
docker compose restart wireguard-amnezia - check the list of kernel modules
dkms status, and check that bunch of[kworker/X:X-wg-crypt-wg0]processes are now running.
- Edit
etc/apt/sources.listand uncommentdeb-src http://archive.ubuntu.com/ubuntu ... main restricted sudo apt updatesudo apt install -y software-properties-common python3-launchpadlib gnupg2 linux-headers-$(uname -r)- install source for kernel
sudo apt-get source linux-image-$(uname -r) sudo add-apt-repository ppa:amnezia/ppasudo apt install -y amneziawgsudo dkms install -m amneziawg -v 1.0.0- restart server or
docker compose restart wireguard-amnezia - check the list of kernel modules
dkms status, and check that bunch of[kworker/X:X-wg-crypt-wg0]processes are now running.
Parameter descriptions can be found in the AmneziaWG documentation and on the kernel module page.
All parameters except I1–I5 will be set automatically at first startup. For instructions on configuring I1–I5, refer to the AmneziaWG documentation.
- If a parameter is not set, it will not be included in the configuration.
- If all AmneziaWG-specific parameters are absent, AmneziaWG is fully compatible with standard WireGuard.
| Parameter | Can differ between server and client | Configurable on server | Configurable on client |
|---|---|---|---|
| Jc | ✅ Yes | ✅ Yes | ✅ Yes |
| Jmin | ✅ Yes | ✅ Yes | ✅ Yes |
| Jmax | ✅ Yes | ✅ Yes | ✅ Yes |
| S1–S4 | ❌ No, must match | ✅ Yes | ❌ No (copied from server) |
| H1–H4 | ❌ No, must match | ✅ Yes | ❌ No (copied from server) |
| I1–I5 | ✅ Yes | ✅ Yes | ✅ Yes |
- Parameters Jc, Jmin, Jmax, I1–I5 can be configured independently on server and client if needed.
- Parameters S1–S4 and H1–H4 must match between server and client; client copies them automatically from the server.
- Use I1–I5 only if you need advanced customization. Otherwise, default automatic values are sufficient.
Amnezia adds random packets to change signature of wireguard protocol and bypass DPI.
By default we use JMIN=20; JMAX=100 for junk packet size in bytes.
Large junk packets can help to bypass DPI, but some firewalls can block them as DDOS attack. Use env variables to change their size if you have issues with amnezia connection:
JC=3
JMIN=20
JMAX=100
or
JC=2
JMIN=10
JMAX=20
Example part of docker-compose.override.yml with JC, JMIN and JMAX:
wireguard-amnezia:
environment:
- WIREGUARD_PASSWORD=xxxxx
- JC=2
- JMIN=10
- JMAX=20
extends:
file: services/wireguard/docker-compose.yml
service: wireguard-amneziaSettings/env variables are saved in ./config/wireguard_amnezia/ folder. To update them remove folder and run container again. This will also remove all existing clients/certificates.
docker compose down && rm -rf ./config/wireguard_amnezia/ && docker compose up -d- OpenWrt setup guide - how to setup OpenWrt router with this solution to keep LAN clients happy.
- Keenetic setup guide - instructions for configuring the server and connecting Keenetic routers to it (на русском языке)
iperf3 server is included in antizapret-vpn container.
- Connect to VPN
- Use iperf3 client on your phone or computer to check upload/download speed.
Example 10 threads for 10 seconds and report result every second:
# local node iperf3 -c az-local.antizapret -i1 -t10 -P10 iperf3 -c az-local.antizapret -i1 -t10 -P10 -R # world node iperf3 -c az-world.antizapret -i1 -t10 -P10 iperf3 -c az-world.antizapret -i1 -t10 -P10 -R
- ProstoVPN — the original project
- AntiZapret VPN Container — source code of the LXD-based container
- AntiZapret PAC Generator — proxy auto-configuration generator to bypass censorship of Russian Federation
- WireGuard VPN — used for Wireguard integration
- OpenVPN - used for OpenVPN integration
- AdGuardHome - DNS resolver
- filebrowser - web file browser & editor
- lighttpd - web server for unified dashboard
- caddy - reverse proxy
- No Thought Is a Crime — a forum about technical, political and economical aspects of internet censorship in different countries
- Dante - SOCKS5 proxy server for per-application routing
