Since I did not want to buy new, expensive IPv4 addresses, or possibly not be able to obtain any in the future, I configured the following setup to provide IPv4 connectivity to pure IPv6 LXC containers or VMs. The concept is mine, but the work is not entirely mine alone; ChatGPT helped me with it and also created the summary. The setup works; access has become significantly faster because there is now an Nginx proxy in front that optimizes the architecture in several ways. However, in DNS some VMs/LXC containers are combined under a single IPv4 and a single IPv6 address. You should carefully consider whether to integrate a mail server into this setup. If one container sends spam, the mail server will also end up on a blacklist because it shares the same IP address. I hope all steps are covered. This is the current state: # Technical system description – edge proxy and WireGuard on Debian 12 with ISPConfig ## 1. System overview This setup describes a Debian 12 installation with ISPConfig that acts as a combined reverse proxy (TLS passthrough) and WireGuard server for IPv4 egress. "Edge proxy" = public dual-stack server, "Client 1" = internal IPv6-only system with IPv4 tunnel. ## 2. Package installation ```bash apt update apt install nginx-full libnginx-mod-stream wireguard iptables ``` If Apache is active via ISPConfig, ensure that it does not listen on ports 80/443 to avoid port conflicts. ## 3. Network concept The edge proxy is dual-stack capable with public IPv4 and IPv6 addresses. Backends (including Client 1) use native IPv6; IPv4 traffic is tunneled via WireGuard. DNS A/AAAA records point to the edge proxy; SSH is performed directly over IPv6. ## 4. Nginx reverse proxy configuration ### 4.1 Host mapping File: `/etc/nginx/maps/host_upstreams.inc` (website mapping) ```text site1.example.net [IPv6-Backend1]; site2.example.net [IPv6-Backend2]; default [IPv6-Default]:443; ``` ### 4.2 TLS SNI mapping and TLS passthrough File: `/etc/nginx/stream-enabled/443-sni-map.conf` ```nginx # TLS SNI → target backend:443, based on /etc/nginx/maps/host_upstreams.inc (without port) # 1) Load SNI → IP (without port) map $ssl_preread_server_name $upstream_ip_v6 { hostnames; # Map URL to server IP for 443 and 80 include /etc/nginx/maps/host_upstreams.inc; } # 2) Build IP → IP:443 map $upstream_ip_v6 $sni_upstream { "~^(.*)$" $1:443; } server { listen 0.0.0.0:443; listen [::]:443; ssl_preread on; proxy_protocol on; proxy_pass $sni_upstream; proxy_connect_timeout 10s; proxy_timeout 180s; access_log /var/log/nginx/stream_access.log stream_fmt; error_log /var/log/nginx/stream_error.log warn; } ``` ### 4.3 HTTP ACME proxy and redirect File: `/etc/nginx/conf.d/80-acme-proxy.conf` ```nginx # 1) Host → IP (without port) from common include file map $host $upstream_ip_v6 { hostnames; # Mapping for ports 80 and 443 include /etc/nginx/maps/host_upstreams.inc; } server { listen 0.0.0.0:80 default_server; listen [::]:80 default_server; server_name _; # 2) Forward ACME challenges to target server on port 80 location ^~ /.well-known/acme-challenge/ { proxy_pass http://$upstream_ip_v6:80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto http; proxy_redirect off; proxy_connect_timeout 5s; proxy_send_timeout 10s; proxy_read_timeout 10s; } # 3) Redirect everything else to HTTPS location / { return 301 https://$host$request_uri; } } ``` ### 4.4 Apache configuration (backend server) File: `/etc/apache2/conf-available/10-remoteip-proxyproto.conf` ```apache RemoteIPProxyProtocol On RemoteIPTrustedProxy RemoteIPTrustedProxy LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined_realip CustomLog ${APACHE_LOG_DIR}/access.log combined_realip ``` Notes: - Replace `` and `` with the actual addresses of the edge proxy. - The edge proxy must actively send the PROXY protocol. - Do not use `RemoteIPHeader` at the same time. - Activation: ```bash a2enmod remoteip a2enconf 10-remoteip-proxyproto systemctl reload apache2 ``` ## 5. WireGuard configuration ### 5.1 Key generation Generate keys (use unique filenames per system, e.g. for the edge proxy and each client separately): ```bash # Edge proxy umask 077 wg genkey > /etc/wireguard/edgeproxy.key wg pubkey < /etc/wireguard/edgeproxy.key > /etc/wireguard/edgeproxy.key.pub # Client 1 umask 077 wg genkey > /etc/wireguard/client1.key wg pubkey < /etc/wireguard/client1.key > /etc/wireguard/client1.key.pub # For additional clients use unique names (client2.key, client3.key, ...) wg genkey > /etc/wireguard/client2.key wg pubkey < /etc/wireguard/client2.key > /etc/wireguard/client2.key.pub ``` ### 5.2 Edge proxy configuration File: `/etc/wireguard/wg0.conf` ```ini [Interface] Address = 10.10.10.1/24 PrivateKey = ListenPort = 51820 PostUp = iptables -t nat -A POSTROUTING -s 10.10.10.0/24 -o -j MASQUERADE PostDown = iptables -t nat -D POSTROUTING -s 10.10.10.0/24 -o -j MASQUERADE [Peer] PublicKey = AllowedIPs = 10.10.10.2/32 # Example: second peer (Client 2) [Peer] PublicKey = AllowedIPs = 10.10.10.3/32 ``` ### 5.3 Client 1 configuration File: `/etc/wireguard/wg0.conf` ```ini [Interface] Address = 10.10.10.2/32 PrivateKey = MTU = 1420 [Peer] PublicKey = Endpoint = [IPv6-of-EdgeProxy]:51820 AllowedIPs = 0.0.0.0/0 PersistentKeepalive = 25 # Optional: second peer (e.g. backup edge proxy) [Peer] PublicKey = Endpoint = [IPv6-of-EdgeProxy-Backup]:51820 AllowedIPs = 0.0.0.0/0 PersistentKeepalive = 25 ```