AntiZapret VPN in Docker

repository·v6·Indexed 42 days ago

https://github.com/xtrime-ru/antizapret-vpn-docker

A split-tunneling VPN solution using DNS-based routing to redirect blocked domains through a VPN tunnel. Supports modular deployment via Docker and Docker Swarm, featuring multiple exit nodes, various VPN protocols (Wireguard, Amnezia Wireguard, OpenVPN), and integrated AdGuardHome for DNS management.

Tokens
33K
Snippets
91
Records
129
Agent score
55%

What's inside AntiZapret VPN

  1. Key Features of AntiZapret VPN

    v6

    The system provides several advanced networking and VPN capabilities:

    • Modular Design: Built using external open-source modules.
    • Web Administration: User-friendly web panels for managing VPN and DNS.
    • Multiple VPN Transports: Supports WireGuard, AmneziaWG, OpenVPN, and OpenConnect (ocserv).
    • DNS Management: Uses AdguardHome as the primary DNS resolver and blocked domain manager.
    • Multi-server Architecture: Allows using different exit nodes for different domains to bypass geo-restrictions.
    • Security: Includes a firewall to protect against port scanning.
    • Performance: Supports kernel modules for OpenVPN and Amnezia Wireguard to reduce CPU load.
    • Application Routing: Provides SOCKS5 and HTTP(S) proxies for routing specific applications through local or foreign exit nodes.
    • Anti-DPI: Built-in support for zapret2 to handle HTTP, TLS, and QUIC traffic.
  2. What is AntiZapret VPN in Docker?

    v6

    AntiZapret is a split-tunneling solution designed to redirect only blocked domains through a VPN tunnel. It uses a modular design based on high-quality open-source containers to provide a seamless experience where only specific traffic is routed through the VPN, while regular traffic uses your local internet connection.

    Core Workflow

    1. Domain Loading: A list of blocked domains is loaded from an open registry.
    2. DNS Parsing: The list is parsed to create rules for the DNS resolver (AdguardHome).
    3. DNS Redirection: AdguardHome redirects requests for blocked domains to a Python script (dnsmap.py).
    4. IP Mapping: The script resolves the real address, creates a fake address from the 14.16.0.0/14 subnet, and creates an iptables rule to redirect traffic from the fake IP to the real IP.
    5. Client Response: The fake IP is sent back to the client in the DNS response.
    6. Routing: VPN tunnels are configured with split tunneling so that only traffic destined for the 14.16.0.0/14 subnet is routed through the VPN.
  3. Configure ocserv templates

    v6

    Configuration for ocserv is managed via persistent templates located at:

    • ./config/ocserv/ocserv.tmpl
    • ./config/ocserv/az.tmpl

    These templates are only created if they do not exist. On every startup, environment variable placeholders in these templates are substituted into the runtime configuration files (/run/ocserv/ocserv.conf and /run/ocserv/config-per-group/az).

    Warning: Always edit the .tmpl files, not the runtime files in /run/. To apply changes made to templates, you must restart the container.

  4. How the DNS resolving algorithm works

    v6

    The system uses a multi-layered DNS approach involving AdGuardHome, CoreDNS, and a dnsmap.py server to intelligently route traffic through VPN exit nodes.

    Core Logic Flow

    1. AdGuardHome receives the request and checks blacklist rules. If a domain is blacklisted, it returns 0.0.0.0.
    2. If not blacklisted, the request is sent to CoreDNS.
    3. CoreDNS queries the internal dnsmap.py server (running in the antizapret container).
    4. dnsmap.py triggers a secondary request back to AdGuardHome using a specific client identity ($client=az-local or $client=az-world).
    5. AdGuardHome processes this internal request:
      • If the domain is in the whitelist, it returns the real IP.
      • If the domain is not in the whitelist, it returns SERVFAIL.
    6. dnsmap.py handles the response:
      • If it's a valid IP, it replaces it with an internal IP from the exit container's subnet (e.g., 14.16.0.0/15 for az-local), adds a masquerade rule to iptables, and returns the internal IP.
      • If it's SERVFAIL, it passes the error back.
    7. CoreDNS handles SERVFAIL by retrying the request directly to AdGuardHome without the special client identity, allowing normal processing for non-VPN domains.
  5. How the DNS resolution algorithm works

    v6

    The system uses a multi-step DNS resolution process involving AdGuard Home, CoreDNS, and a custom dnsmap.py script to achieve selective routing through VPN exit nodes.

    Core Logic Flow

    1. AdGuard Home receives the request. If the domain is in a blacklist, it returns 0.0.0.0 (blocked).
    2. If not blocked, AdGuard forwards the request to CoreDNS.
    3. CoreDNS queries the internal dnsmap.py server.
    4. dnsmap.py triggers a secondary request back to AdGuard using a specific client identity (e.g., az-local) and a real upstream (e.g., 8.8.8.8).
    5. AdGuard applies whitelist/blacklist rules for that specific client identity:
      • If Whitelisted: AdGuard returns the real IP to dnsmap.py.
      • If Not Whitelisted: AdGuard returns SERVFAIL.
    6. dnsmap.py processing:
      • If it receives a valid IP: It replaces the IP with an "internal" IP from the exit node's subnet (e.g., 14.16.0.0/15 for az-local), adds iptables masquerading, and returns the internal IP to AdGuard.
      • If it receives SERVFAIL: It passes the SERVFAIL to the client.
    7. Fallback: If CoreDNS receives SERVFAIL, it retries the request directly to AdGuard without the special client identity, allowing the request to be processed normally (returning the real IP).

    Why this complexity exists

    • Client Compatibility: Some clients (like Windows) don't retry fallback DNS on SERVFAIL. CoreDNS handles this retry.
    • AdGuard Limitations: AdGuard doesn't allow overriding upstreams within blacklist/whitelist rules. The multi-request trick bypasses this.
    • Granular Control: Using different client identities (az-local, az-world) allows AdGuard to use different upstreams for blocked vs. unblocked domains.
  6. Configure OpenVPN client on Keenetic routers

    v6

    OpenVPN is the most reliable method for bypassing blocks on Keenetic routers. For optimal performance, use high-end models with fast processors (1 GHz+) and at least 256 MB RAM (e.g., Peak, Giga, Hopper, Sprinter, Challenger SE, or Ultra).

    Setup Steps:

    1. Install Component: Ensure the "OpenVPN Client and Server" component is installed via the Keenetic component manager.
    2. Prepare Configuration: Add the following lines to your OpenVPN configuration file:
      pull-filter ignore block-outside-dns
      route 77.88.8.8
    3. Create Connection:
      • Navigate to Internet > Other connections > VPN connections > Add connection.
      • Set Use for internet access to NO.
      • Name: AntiZapret.
      • Protocol: OpenVPN.
      • Get routes from remote side: YES.
      • Paste the configuration content from step 2 into the configuration field.
      • Save.
    4. Configure DNS and Filtering:
      • Go to Network rules > Internet filters.
      • DNS Setup: Add a new profile named AntiZapret. Set DNS query transit to NO. Add a server with Type Default and IP 77.88.8.8. Save.
      • Content Filter: Set Filtering mode to Public DNS resolvers. Assign the AntiZapret profile to your default content filtering profiles (e.g., guest and home).
    5. Enable Connection: Go to Internet > Other connections and enable the AntiZapret connection.
    pull-filter ignore block-outside-dns
    route 77.88.8.8
  7. Configure Amnezia WireGuard on Keenetic router

    v6

    If you are using Amnezia WireGuard, you must perform additional steps via the router's Command Line after following the standard WireGuard setup.

    1. Open the router web interface, click the gear icon (top right), and select Command Line.
    2. Run the command: show interface.
    3. Find your connection's interface name. Search (Ctrl+F) for your connection name (e.g., AntiZapret) and look for the interface-name field (e.g., Wireguard1).
    4. Construct the configuration command using the asc parameters from your .conf file. The template is: interface {name} wireguard asc {jc} {jmin} {jmax} {s1} {s2} {h1} {h2} {h3} {h4} Replace the bracketed values with your actual parameters and remove the brackets.
    5. Paste the resulting string into the Command Line and click Send Request.
    6. Run the command: system configuration save to persist changes.
    7. Enable the connection in Internet > Other Connections.
    interface Wireguard1 wireguard asc 8 50 1000 30 32 1811016522 1196729875 457766807 1765857463
  8. Install AntiZapret via Single Server (Easy Mode)

    v6

    This method is recommended for most users. It runs a single az-local exit container that handles both local and world domain lists using the 14.16.0.0/15 range. It is best to host this on a server located in a western country to avoid geo-restrictions.

    Prerequisites:

    • Root access (required to prevent inconsistent file permissions and container reboot loops).
    • Docker Engine installed.

    Steps:

    1. Install Docker Engine.
    2. Clone the repository and checkout the v6 branch.
    3. Create a docker-compose.override.yml to specify the services you want to use (e.g., adguard, wireguard).
    4. Start the services using docker compose up -d.
    # 0. Install Docker
    curl -fsSL https://get.docker.com -o get-docker.sh
    sudo sh get-docker.sh
    
    # 1. Clone and checkout
    git clone https://github.com/xtrime-ru/antizapret-vpn-docker.git antizapret
    cd antizapret
    git checkout v6
    
    # 2. Create docker-compose.override.yml (Example for Wireguard)
    # services:
    #   adguard:
    #     environment:
    #       - ADGUARDHOME_PASSWORD=somestrongpassword
    #   wireguard:
    #      environment:
    #         - WIREGUARD_PASSWORD=somestrongpassword
    #      extends:
    #         file: services/wireguard/docker-compose.yml
    #         service: wireguard
    
    # 3. Start services
    docker compose up -d
    docker system prune -f
  9. Configure custom sites in Caddy

    v6

    You can expose additional services by adding Caddy configuration files to config/https/config/sites-enabled. The https container automatically imports these files.

    To expose a service (e.g., my-app on port 8080) via a domain, create a file like config/https/config/sites-enabled/my-app.caddy:

    example.com {
      reverse_proxy my-app:8080
    }

    After adding or changing configuration, restart the container:

    docker service update --force antizapret_https || docker compose restart https
  10. Update the VPN deployment

    v6

    Single Instance Update

    git pull --rebase
    docker compose down --remove-orphans
    docker compose up -d --remove-orphans
    docker system prune -af

    Docker Swarm Update

    git pull --rebase
    docker pull xtrime/antizapret-vpn:6
    docker compose --env-file compose.swarm.env config | docker run --pull always --rm -i xtrime/antizapret-vpn:6 compose2swarm | docker stack deploy --prune -c - antizapret
    docker system prune -af