-1

I am trying to access a router settings web page from Internet.

I have setup a WireGuard VPN on AWS EC2. The handshake between the router and the WireGuard server looks good, but I am not able to access the url using the public IP of the ec2 instance - http://y.y.y.y:51820.

Does anyone have a solution?

Server

[Interface]
Address = 172.31.16.1/20
SaveConfig = true
ListenPort = 51820
PrivateKey = PrivateKey
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

Handshake details below

Server

interface: wg0
  public key: public key
  private key: (hidden)
  listening port: 51820

peer: public key
  endpoint: x.x.x.x:6140
  allowed ips: 172.31.16.2/32
  latest handshake: 2 minutes, 1 second ago
  transfer: 13.91 KiB received, 3.77 KiB sent

Client

interface: wg0
  public key: public key
  private key: (hidden)
  listening port: 46734

peer: public key
  endpoint: y.y.y.y:51820
  allowed ips: 0.0.0.0/0
  latest handshake: 2 minutes, 7 seconds ago
  transfer: 3.77 KiB received, 16.08 KiB sent
  persistent keepalive: every 25 seconds

2 Answers 2

0

Wireguard Config

There is a collision between your WG subnet and the external interfaces subnet. The WG subnet needs to be separate. 10.8.x.0/24 is a common choice. PUtting a random x can make "sure" it is unique. Also putting KeepAlive=20 on both sides will ensure that the firewall punch of the tunnel packets from the router to the vps stays open. Otherwise if no communication for some time, the vps may not be able to transmit the first packet through the tunnel.

Server wg0.conf

[Interface]
Address = 10.8.0.1/24
SaveConfig = true
PreUp = iptables -t nat -I PREROUTING -p tcp --dport 50400 -j DNAT --to-destination 10.8.0.2:443
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -i eth0 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
ListenPort = 51820
PrivateKey = ********************************

Client conf

[Interface]
Address = 10.8.0.2/24
ListenPort = 51820
PrivateKey = ********************************

Routing

On the server (exposed to the internet), check out the following commands output:

ip rule

ip route

Should show something like 10.8.0.0/24 dev wg0 proto kernel scope link src 10.8.0.1 Or the The most restictive 10.8.0.2 dev wg0 proto kernel scope link src 10.8.0.1.

Ping server from the router, and the reciprocal via the 10.8.0.0/24 subnet. If that works, WG is effective and your routes too.

Firewall work

First need to check if your web interface port is open on the router. Hence from the server, execute:

curl http://10.8.0.2
curl -k https://10.8.0.2 (the -k is to avoid cert verification if you have a self-signed certificate).

If that works, the port to forward to will be 443, avoid exposing 80 as it will go clear on the internet. (If only plain http works, you'll need to find a way (like another VPN) to your server to avoid anything in clear on the internet. Or stunnel to encapsulate, or a reverse proxy etc.)

Forwarding must be enabled in the kernel echo 1 > /proc/sys/net/ipv4/ip_forward

Now comes the fun ! Ref. http://www.do1618.com/wp-content/uploads/2016/06/netfilter_pkt_flow.png The following rules are needed. You can embed them all in the server Wiregard commands run by the config file once confirmed it works. Let's just follow a packet travelling through the server.

iptables -t nat -I PREROUTING -p tcp --dport 50400 -j DNAT --to-destination 10.8.0.2:443

(this performs the destination nat: any request packet received from the internet will see its destination address and port rewritten, before even reaching the route check.)

iptables -A FORWARD -i eth0 -j ACCEPT

(The kernel routing system will identify at the route check that it goes to an exiting interface and not to be input and delivered to a local process. Hence the packet will go through the forward hook. This rule will allow any packet coming from the external interface to be forwarded.

iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE

(The packet will then be sent out via wg0 as per the routing table. However if left as it is, the source ip address remains the one from the requester on the internet. The packet will go to the router and be treated. BUT the router will reply to the originating source address. Without more info and work on the router, the reply return path may be different. Without even going into the kernel reverse path policy setting story, firewalls may not let the packet reach nor enter the originating machine. Masquerading NATs with an automagically determined source address using the outgoing interface. And NATs back the other way on the reply packets. Cf. Gotcha below though)

iptables -A FORWARD -i wg0 -j ACCEPT

(this is to allow reply packets to go through the server from the tunnel to the internet).

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

(this is to make the reply from the router not originate from 10.8.0.2 but rather from the server public address. So firewalls will let it travel back to your laptop.

Gotchas

Masquerading the wg0 interface is a bit dirty. One may want to tweak the router in marking incoming packets with some meta mark, and have a specific rule to route back the reply marked packets to the WG tunnel. But that's some more work and not sure if the router OS will allow the tweaks. Here the only disadvantage is that the router cannot log where people logged from, it will always report 10.8.0.1, wherever your connected from.

Security-wise, the wg0 interface on the router lets you access anything on your router. So it seems it went into the Openwrt LAN zone. Not initially that big a deal when setting up, but one would prefer to set a specific firewall zone, assign the wg0 interface to it, and allow only incoming packets for port 443. As long as the server is secured, nothing else should go through and that acts as a firewall, but still.

Tip - network analyzer Wireshark on console

Install package "tshark" (Ubuntu) or wireshark-cli (Redhat's) on the server

sudo tshark -i any -Y !ssh

Will show packets through all interfaces, excluding the ssh packets to your laptop/PC which would pollute your output.

  • Run this on the server and leave it write.
  • Try to access from your browser https://public_ip:50400 With this it should be easy to see packet flowing between interfaces, and see what goes wrong. You should see the request arriving, the packet going through the vpn interface, and a reply from the vpn interface coming in, and then exiting via eth0 with eth0 source address port 50400, destinated to your browser address on its random port used for the query.
1
  • You are awesome! This worked perfectly. Thanks very much!
    – TechGuy
    Commented Mar 17 at 23:43
1

It seems the server ip (endpoint) is y.y.y.y, but that 51820 is the Wireguard listeneing port. And your iptables commands do not seem to forward specific ports.

Hence the http request will end up on the server without being delivered to a webserver socket.

So y.y.y.y:80 or y.y.y.y:8080 or y.y.y.y:443 or y.y.y.y:zzz (if you have a specific webserver zzz listening port) may be more what is needed for the http(s) request.

NB: Great explanation on how wg-quick sets up routing policy based routing, as well as Wireguard routing page


I believe you need to go through the following:

CLIENT
------
[Interface]
Address = 10.8.0.2/24
#SaveConfig = true
PrivateKey = 

[Peer]
PublicKey = 
PresharedKey = 
Endpoint = y.y.y.y:60000
AllowedIPs = 0.0.0.0/0,::0/0
PersistentKeepalive = 15

SERVER
------
[Interface]
Address = 10.8.0.1/24
#SaveConfig = true
ListenPort = 60000
PrivateKey = 

[Peer]
PublicKey = 
PresharedKey = 
AllowedIPs = 10.8.0.2
PersistentKeepalive = 15
  1. Setup internal WG routing.
  • Set fixed internal IPs as per example on the answer. Set on the same way the ip on the client config file in the Interface. NB: there is no real concept of client and server here, just endpoints and AllowedIPs for Cryptokey routing internally to WG.
  • The router needs to know the endpoint publicly accessible, the other way needs no endpoint.
  • The router port will be random when establishing connection with the server and does not need to be set. Ensure the WG listening port is open on server firewall.
  1. Ping internally client and server to ensure you can route in the tunnel between 10.8.0.1 and 10.8.0.2. No iptables work required here as long as the ports on both sides are open for WG to communicate: this is all inside Wireguard.

  2. Once that is confirmed, ensure the web port XXX on your client (router) is open on its wg0 interface (or whatever interface Wireguard creates on the router). Log onto the SERVER and try to curl the 10.8.0.2:XXX. If that works, you're 99% there. –

  3. Forward server port to router client Will just remain to forward any port of your choice YYYY on the server input to the 10.8.0.2 port XXX. I am more familiar with nftables than iptables. If you are on a RedHat-like, firewalld will let you do that in a very short command too.

You should reach something like that.

  • KeepAlive is to ensure any NAT / firewall stays open even if your 2 machines do not communicate for some time (like 30 sec typically). Else WG packets would get lost if server tries to contact the router.
  • SaveConfig is a pain that overrides config file periodically; better not to.
12
  • Thanks very much for your reply/suggestion/information. I will try this and let you know.
    – TechGuy
    Commented Mar 11 at 16:13
  • 1. As per your suggestion I set the webserver listening port to 29418 (y.y.y.y:29418)
    – TechGuy
    Commented Mar 11 at 22:37
  • 2) I set the port forwarding by executing - sudo iptables -t nat -A PREROUTING -i eth0 -p tcp -d y.y.y.y --dport 29418 -j DNAT --to-destination y.y.y.y
    – TechGuy
    Commented Mar 11 at 22:45
  • 3) I am not able to change the client listening port. So I am using the provided port while setting wg0 at the server. After doing all this, there is still no success. I must be doing something wrong.
    – TechGuy
    Commented Mar 11 at 22:45
  • Hi. I am no world-class expert, but in my opinion, the problem may come from this if I understand correctly: you have a non-internet-accessible router (client here) and a publicly accessible server with ip y.y.y.y. Commented Mar 12 at 20:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .