2

I set up a wireguard tunnel between an AWS instance (acting as server) and a personal computer acting as client. Wireguard is installed on both in a docker container (using linuxserver image). On the local computer I have a website that I would like to access from the server using a proxy with Nginx. Basically I want to connect to the ip of the AWS instance and be redirected through the Wireguard tunnel to the website on my local machine. I can curl my website from the docker container of Nginx on the AWS instance but the proxy doesn't work. How can I solve this problem?

AWS instance (Wireguard server and Nginx proxy)

version: "3" services: reverseproxy: container_name: reverseproxy build: . restart: unless-stopped network_mode: service:wireguard wireguard: image: lscr.io/linuxserver/wireguard:latest container_name: wireguard cap_add: - NET_ADMIN - SYS_MODULE environment: - PUID=1000 - PGID=1000 - TZ=Europe/Rome - SERVERURL=107.22.140.0 #optional - SERVERPORT=51820 #optional - PEERS=1 #optional - PEERDNS=auto #optional - INTERNAL_SUBNET=10.0.0.0 #optional - ALLOWEDIPS=0.0.0.0/0 #optional - LOG_CONFS=true #optional volumes: - /home/ubuntu/wireguard/config:/config - /lib/modules:/lib/modules ports: - 51820:51820/udp - 80:80 sysctls: - net.ipv4.conf.all.src_valid_mark=1 restart: unless-stopped 

Nginx configuration of the proxy:

worker_processes 1; events { worker_connections 1024; } http { sendfile on; upstream docker-proxy { server 10.0.1.2: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-Host $server_name; server { listen 80; resolver 127.0.0.11 ipv6=off; location / { proxy_pass http://docker-proxy/; proxy_redirect off; } } } 

Local machine with Wireguard and local website:

version: '3' services: nginx: container_name: nginx #depends_on: #- reverseproxy image: nginx:alpine restart: unless-stopped ports: - 80:80 networks: vpn: ipv4_address: 10.0.1.2 wireguard: image: lscr.io/linuxserver/wireguard:latest container_name: wireguard cap_add: - NET_ADMIN - SYS_MODULE environment: - PUID=1000 - PGID=1000 - TZ=Europe/Rome - SERVERURL=wireguard.domain.com #optional - SERVERPORT=51820 #optional - PEERS= #optional - PEERDNS=auto #optional - INTERNAL_SUBNET=10.0.0.0 #optional - ALLOWEDIPS=0.0.0.0/0 #optional - LOG_CONFS=true #optional volumes: - /home/user/dev/nginx-proxy/config:/config - /lib/modules:/lib/modules ports: - 51820:51820/udp sysctls: - net.ipv4.conf.all.src_valid_mark=1 restart: unless-stopped networks: vpn: ipv4_address: 10.0.1.5 networks: vpn: ipam: config: - subnet: 10.0.1.0/8 
3
  • At the first sight I don't see any problems. Did you try packet capturing to see how packets go (or don't go) through the network? Commented Jun 25, 2022 at 14:25
  • No, how could I do that? Should I use tcpdump on the host or on one of the containers? Commented Jun 25, 2022 at 15:03
  • Try doing it everywhere. For example, when you're going to listen on the wireguard interface, you have to run it wherever wireguard is running. And on both sides, to confirm that packets that entered the tunnel exit it and then entered the correct Nginx container. I don't really know your complete network layout, so it's hard to give better suggestions. Commented Jun 25, 2022 at 15:08

1 Answer 1

3

If all you want is port forwarding from your AWS server, you don't need nginx, you can just use an iptables rule in your WireGuard container to forward port 80.

On your AWS server, save this WireGuard config file in some directory, like as server/wireguard/wg0.conf:

# server/wireguard/wg0.conf # local settings for AWS server [Interface] PrivateKey = <server private key> Address = 10.0.0.1/32 ListenPort = 51820 # port forwarding to Docker `nginx` service on `vpn` network on personal computer PreUp = iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.0.1.2 # masquerading for Internet traffic to Docker `vpn` network on personal computer PreUp = iptables -t nat -A POSTROUTING -d 10.0.1.0/24 -j MASQUERADE # remote settings for personal computer [Peer] PublicKey = <client public key> AllowedIPs = 10.0.0.2/32, 10.0.1.0/24 

Replace <server private key> with the WireGuard private key you generated for your server, and <client public key> with the WireGuard public key you generated for your client.

Then save this Docker Compose file in the directory above it, like as server/docker-compose.yml:

# server/docker-compose.yml version: '3' services: wireguard: image: procustodibus/wireguard cap_add: - NET_ADMIN ports: - 80:80 - 51820:51820/udp volumes: - ./wireguard:/etc/wireguard 

And run docker-compose up from the same directory as the Docker Compose file.

Next, on your personal computer, save this WireGuard config file in some directory, like as client/wireguard/wg0.conf:

# client/wireguard/wg0.conf # local settings for personal computer [Interface] PrivateKey = <client private key> Address = 10.0.0.2/32 ListenPort = 51820 # masquerading for WireGuard traffic to Docker `vpn` network on personal computer PreUp = iptables -t nat -A POSTROUTING -d 10.0.1.0/24 -j MASQUERADE # remote settings for AWS server [Peer] PublicKey = <server public key> AllowedIPs = 10.0.0.1/32 Endpoint = <server ip address or domain name>:51820 PersistentKeepalive = 25 

Replace <client private key> with the WireGuard private key you generated for your client, and <server public key> with the WireGuard public key you generated for your server. Replace <server ip address or domain name> with the public IP address or domain name of your AWS server.

Then save this Docker Compose file in the directory above it, like as client/docker-compose.yml:

# client/docker-compose.yml version: '3' services: nginx: image: nginx networks: vpn: ipv4_address: 10.0.1.2 wireguard: image: procustodibus/wireguard cap_add: - NET_ADMIN networks: vpn: ipv4_address: 10.0.1.5 ports: - 51820:51820/udp volumes: - ./wireguard:/etc/wireguard networks: vpn: ipam: config: - subnet: 10.0.1.0/24 

And run docker-compose up from the same directory as the Docker Compose file.


However, if you do need nginx on your AWS server (for example to preserve the real IP address of HTTP clients, or to terminate TLS, etc), skip the port-forwarding iptables rule in your AWS server's WireGuard config:

# server/wireguard/wg0.conf # local settings for AWS server [Interface] PrivateKey = <server private key> Address = 10.0.0.1/32 ListenPort = 51820 # masquerading for Internet traffic to Docker `vpn` network on personal computer PreUp = iptables -t nat -A POSTROUTING -d 10.0.1.0/24 -j MASQUERADE # remote settings for personal computer [Peer] PublicKey = <client public key> AllowedIPs = 10.0.0.2/32, 10.0.1.0/24 

Add save your reverse-proxy nginx config file on the AWS server in a directory that's a sibling of your WireGuard config, like server/reverseproxy/nginx.conf:

# server/reverseproxy/nginx.conf events {} http { server { listen 80; location / { proxy_pass http://10.0.1.2:80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } } 

Use whatever proxy directives (or other nginx config) you want in this config file (the original reverse-proxy config from your question should work fine) -- just make sure the upstream server address and port matches the address and port used by the Docker nginx service in the vpn network on your personal computer.

Then add this reverseproxy service to the Docker Compose config on your AWS server:

# server/docker-compose.yml version: '3' services: reverseproxy: image: nginx network_mode: service:wireguard volumes: - ./reverseproxy:/etc/nginx wireguard: image: procustodibus/wireguard cap_add: - NET_ADMIN ports: - 80:80 - 51820:51820/udp volumes: - ./wireguard:/etc/wireguard 

On your personal computer, use the same "client" WireGuard and Docker Compose config from the first part of this answer.

3
  • Thank you for the clear response! I tried both methods but I wasn't able to get any of them to work. Without using a proxy on the AWS I get Empty reply from server when running curl localhost on the AWS server itself and nothing when running curl from my computer. Adding the proxy I get the web page of my local machine but only when running curl localhost on the AWS server. Commented Jul 6, 2022 at 18:07
  • 1) Do your EC2 security-group rules allow you to connect to port 80 on the AWS server from your computer? (try running a plain nginx container on port 80 of the AWS server to double-check) 2) When testing, make sure you always (re-)start the "client" containers (on your computer) after you (re-)start the "server" containers (on the AWS server) -- otherwise you may have to wait a couple minutes for the client to forget its old WireGuard connection state and re-connect to the server Commented Jul 7, 2022 at 2:13
  • Sincerely thank you for this clear answer, really saved me from hours of googling Commented Jul 11, 2023 at 17:41

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.