point-to-site WireGuard VPN on CentOS 7 with firewalld, cannot connect to internal LAN except with firewalld stopped

Issues related to configuring your network
Post Reply
Shore-Bank
Posts: 8
Joined: 2021/02/06 00:47:57

point-to-site WireGuard VPN on CentOS 7 with firewalld, cannot connect to internal LAN except with firewalld stopped

Post by Shore-Bank » 2021/02/06 02:21:27

Hey all - I come to you looking for sage advice!

So, I SEEM to have my WireGuard setup... sort of correct. In that, I appear to be able to connect to it from my Mac (tethered to my iPhone), and I can see via the `wg` command that I'm getting regular handshakes. I can ping to devices on our internal LAN, but I cannot resolve their hostnames (e.g. intranet.example.com)... UNLESS I disable firewalld via a # systemctl stop firewalld. Then, things SEEM to work fine. This is suboptimal from a security perspective, obviously.

That said, I just ran a tcpdump on my wg0 interface on the server, and they very much DO NOT appear to be working fine, since my Mac appears to be trying to route... uhm, everything over WireGuard, despite having very clear rules in the client config. I should only be routing traffic that corresponds to our internal LAN IPs over WireGuard, and everything else should be left alone. Yet, I'm seeing everything from YouTube to Zoom requests being forwarded to our internal DNS servers.

Sanitized, here are my configs:

Server: (located on the DMZ subnet at 172.20.20.12, NATed to from its public IP, 1.2.3.4)

Code: Select all

[Interface]
Address = 192.168.21.1/24
ListenPort = 51820
PrivateKey = server_private_key

[Peer]
PublicKey = peer_1_public_key
AllowedIPs = 192.168.21.2/32

[Peer]
PublicKey = peer_2_public_key
AllowedIPs = 192.168.21.3/32

[Peer]
PublicKey = peer_3_public_key
AllowedIPs = 192.168.21.4/32
Client: (we'll call this my Mac)

Code: Select all

[Interface]
Address = 192.168.21.3/24
PrivateKey = peer_2_private_key

DNS = 192.168.20.10, 192.168.20.11

[Peer]
PublicKey = server_public_key
# I do not know why my Mac is sending all traffic given the line below in my config.
AllowedIPs = 192.168.20.0/24, 192.168.21.0/24, 218.219.220.37/32
Endpoint = wireguard.example.com:51820

# This is recommended by WireGuard docs for people behind NAT, so I figured I'd enable it
PersistentKeepalive = 25
firewalld rules: (I'm a fan of simple, if anyone wants to point out where I can make things simpler)

Code: Select all

# firewall-cmd --list-all-zones # (but with irrelevant zones omitted)
dmz (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens160
  sources: 
  services: https ssh wireguard
  ports: 
  protocols: 
  masquerade: yes
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

work (active)
  target: default
  icmp-block-inversion: no
  interfaces: 
  sources: 192.168.21.0/24
  services: ssh wireguard
  ports: 
  protocols: 
  masquerade: yes
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules:
System Logs:

Code: Select all

Feb  5 12:00:00 wgu kernel: FINAL_REJECT: IN=ens160 OUT= MAC=ff:ff:ff:ff:ff:ff:00:50:56:b7:c0:d6:08:00 SRC=0.0.0.0 DST=255.255.255.255 LEN=311 TOS=0x00 PREC=0xC0 TTL=64 ID=0 DF PROTO=UDP SPT=68 DPT=67 LEN=291 
Feb  5 12:00:09 wgu kernel: FINAL_REJECT: IN=ens160 OUT= MAC=ff:ff:ff:ff:ff:ff:00:50:56:b7:c0:d6:08:00 SRC=0.0.0.0 DST=255.255.255.255 LEN=311 TOS=0x00 PREC=0xC0 TTL=64 ID=0 DF PROTO=UDP SPT=68 DPT=67 LEN=291 
Feb  5 12:00:18 wgu kernel: FINAL_REJECT: IN=ens160 OUT= MAC=ff:ff:ff:ff:ff:ff:00:50:56:b7:c0:d6:08:00 SRC=0.0.0.0 DST=255.255.255.255 LEN=311 TOS=0x00 PREC=0xC0 TTL=64 ID=0 DF PROTO=UDP SPT=68 DPT=67 LEN=291
Notes:

1. Regardless of whether or not firewalld is running, I am able to connect to the WireGuard peer acting as the site server.
2. Regardless of whether or not firewalld is running, I am able to ping the server at 192.168.21.1 from my Mac, and I am able to ping my Mac at 192.168.21.3 from the server. I am also able to ping hosts on the company's internal network, at 192.168.20.0/24. I can ping the DNS servers, and I can ping other servers running HTTPS servers - but that is ALL I can do.
3. With the firewalld service stopped, I am able to reach HTTPS services running on our internal network by hostname. This is why I am convinced that my primary issue lies with my firewalld configuration, specifically something that takes place when that WireGuard packet gets to the server, and must go on to the real network.

As far as why my Mac is sending all traffic over the VPN? I couldn't tell you. Absolutely baffled at that. Don't expressly care, it's out of scope of this question, I'll figure that out once I've got the server config stable and good to go.

As far as why I cannot get to other internal services, I feel like there's some kind of fancy iptables forwarding rule that I'm just not sure how to translate into firewalld-speak.
Last edited by Shore-Bank on 2021/02/09 20:37:14, edited 2 times in total.

User avatar
jlehtone
Posts: 4523
Joined: 2007/12/11 08:17:33
Location: Finland

Re: point-to-site VPN on CentOS 7 with firewalld, cannot connect to internal LAN except with firewalld stopped

Post by jlehtone » 2021/02/06 11:54:56

I assume that you have routed setup. (Config looks like it, but I can't tell.) In routed setup your VPN server has links to three subnets:
(1) company LAN, (2) WAN, and (3) VPN. The client has two links: (1) WAN and (2) VPN.

Expected behaviour:
1. A packet "A" arrives from WAN (SRC=client WAN IP) to wireguard
2. A packet "B" arrives from VPN (SRC=client VPN IP)
3. Packet "B" traverses netfilter's FORWARD chain
4. Packet "B" leaves via LAN
5. Reply to B (DST=client VPN IP) enters from LAN
6. Reply traverses netfilter's FORWARD chain
7. Reply leaves via VPN
8. Wireguard sends reply to A (DST=client WAN IP) via WAN

In bridged setup there is no separate VPN subnet; the client has a company LAN IP address as its VPN address and traffic does not pass the FORWARD chain.

Firewalld (in CentOS 7 and 8) practically does not support routing.
Upstream https://firewalld.org/2020/09/policy-ob ... troduction writes:
With some exceptions (e.g. masquerade, forward-ports) firewalld was previously limited to being an end-station firewall. This meant you could not use it to filter traffic flowing between virtual machines, containers, and zones. A subset of that functionality was available by using the direct interface and writing your own iptables rules, but it wasn’t a great user experience.
If you disable firewalld, then you do disable masquerade. Edge routers usually require masquerade.

It is typical for VPN (server config) to push the default route to clients. This can be convenient, you connect to your company network with VPN and then your client appears to be in the company network as far as outsiders know (routing all traffic via company's edge router).

I have set my client to ignore the offered default route. That way my client uses VPN route only for select destinations.
Don't know WireGuard.


There are thus five options:
1. Change to bridged. (Probably not a good idea.)
2. Make WireGuard add necessary forwarding rules. (No idea if it can talk to firewalld.)
3. Add "direct rules". (Not simple.)
4. Replace firewalld.service with iptables.service and write the ruleset yourself. (Result can be simple, but writing it ...)
5. Play with zones. (Might be ok.)

With routed setup you (should) have three zones. WAN (dmz), LAN, and VPN.
What if you set the VPN to "trusted" zone?
The "trusted" allows everything, including routing from/to it.

You can see the current ruleset with:

Code: Select all

iptables -S
iptables -t nat -S
iptables -t mangle -S

Shore-Bank
Posts: 8
Joined: 2021/02/06 00:47:57

Re: point-to-site WireGuard VPN on CentOS 7 with firewalld, cannot connect to internal LAN except with firewalld stopped

Post by Shore-Bank » 2021/02/17 00:45:45

I actually got it working. I had to ditch firewalld, and install iptables:
  1. # systemctl stop firewalld - Stop the firewalld service.
  2. # systemctl disable firewalld - Prevent the firewalld service from running at startup.
  3. # systemctl mask --now firewalld - Prevent other services from calling firewalld.
  4. # yum install iptables-services - Install iptables.
  5. # systemctl start iptables && systemctl start ip6tables - Start iptables.
  6. # systemctl enable iptables && systemctl enable ip6tables - Ensure iptables runs at startup.
Then I configured my iptables rules - they were super simple (though I may tighten them down a little more as I begin to better understand iptables) by setting the following: (link1, link2)
  • # iptables -A INPUT -i lo -j ACCEPT - Rule permitting traffic on the loopback adapter, so that other programs and services that often depend on it can work correctly.
  • # iptables -A INPUT -p icmp -j ACCEPT - Rule permitting ICMP traffic (like ping, etc) for troubleshooting. Enable / disable at your discretion.
  • # iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT - Rule to permit certain connections based on their relationships to previous ones.
  • # iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT - Rule permitting SSH.
  • # iptables -A INPUT -p udp -m udp --dport 51820 -j ACCEPT - Rule permitting WireGuard.
  • # iptables -A INPUT -j DROP - Categorical drop. Once a packet has passed through all of the rules above and failed to match any of them, it should be dropped, not allowed in.
  • # mv /etc/sysconfig/iptables /etc/sysconfig/iptables.bak - Backup your system's default iptables rules.
  • # iptables-save > /etc/sysconfig/iptables - iptables rules are ephemeral, so restarting the iptables services or rebooting the box will reset them! You need to save them so that the server will retain them persistently through reboots.
  • # iptables -L or # iptables -S to view your iptables rules.
I actually have a bit of a more complex system in our network with FOUR WireGuard interfaces listening on different ports, so I intend to update my iptables rules to better secure the traffic on them and between the subnets they are permitted on.

Post Reply