h44z / wg-portal

WireGuard Configuration Portal with LDAP connection
https://wgportal.org/
MIT License
951 stars 127 forks source link

Filter outgoing IP for clients on server side #42

Open ItterVH opened 3 years ago

ItterVH commented 3 years ago

Has anyone solved the problem of filtering outgoing connections for wierguard clients on the server side without using AllowedIPs on the client side or in combination with it? Something like a whitelists, easy to edit, ideally for each client its own. I would be grateful if someone would advise an existing solution.

chibomorto commented 3 years ago

Hello ItterVH. I’m not sure i understand your question. I’m also not sure I can help you, since I’m come from social sciences and this is a recent hobby. Trying to help you I ended up having my own question. I did not understand, at first, logic behind the server and client configuration of allowed IP (and probably I still don’t!). If I got it correctly, on the server side you set the default allowed IPs. That´s the value that wg-portal will set by default to every peer that is created on the interface.conf file (wg0.conf) when you add a new client on wg-portal. If you choose to set a different AllowedIP on the client configuration tab, it will override the default allowed IP, setting an exclusive configuration for that peer on the respective peer entry of the .conf file. For that you have to check “Ignore Global Settings”. Until I read your question, all my clients had the same default configuration. I’ve tried to create a new peer, following that logic, with custom AllowedIPs created on the client side and It just didnt’t work. The client on the interface.conf file is created exclusively with the Peer IP, and the “Ignore Global Settings” apparently doesn’t work. Searching for an answer, I found Issue #24 that seams similar to this question. Supposing that that I have wg-portal working in server mode, with the IP 10.254.0.1 and that Default Allowed IPs are 10.254.0.0/24, how do I set a client to connect exclusively to a home network resource that is available at 192.168.1.100 (192.198.1.100/32)?

ItterVH commented 3 years ago

My question is for the case when a wireguard subnet has forwarding to an interface connected to the Internet and there is a need to allow clients to connect strictly to certain addresses on the Internet using a whitelist. If this is configured only on the client side, a smart client can replace the AllowedIPs list with 0.0.0.0/0 and be completely free to commit unnecessary disgrace.

ItterVH commented 3 years ago

The issue is solved by post-up / post-down scripts with iptable rules. Something like this:

ip_pool="10.6.6.0/24"
while read -r ip; do
iptables -A FORWARD -i wg0 --source $ip_pool --destination $ip -j ACCEPT
done < $whitelist
iptables -A FORWARD -i wg0 -j DROP
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Question to the developer - is it possible to somehow get access to the AllowedIPs list that is stored in the portal database? It would be nice to be able to export it to a plain text file to use as a whitelist.

EugenMayer commented 3 years ago

Sorry, kinda long IMHO - but i find this one of the more important topics around wireguard (IMHO)

I think it is best practice to run a firewall in any case with WG. Since the client can set the AllowedIps to whatever it likes, not tighten up the server side will have sensible consequences.

I'am new to wireguard, coming from OpenVPN and not used to the concept 'the client tells the server what he want to access' - this is really odd (by wireguard) - but it is conceptual by wireguard itself.

This said, once can simply limit using firewall forward rules, what the wg clients will be able to access (no matter of their wish).

This said, not sure this should be part of wg-portal at all, but if, it would be a huge responsibility and quiet a big effort too.

Concept/Design A "all clients are equal":

Either we define that for one wg-instance (those one wg bridge) we consider all clients to be 'equally limited in their scope' - thus we can basically start up wireguard on wg0 and create the forward rules ourselves using the known allowedIps configuration (and this could be something wg-portal could do). E.g. wg-easy does something 'similar' (but not really using allowedIps at all).

I think this concept is mostly aligned how wireguard itself was designed - anything beyond 'all clients are equal' seems to be rather at home with openVPN in the first place.

In this concept, if we want different client-types with different limitations, we would use an additional wg1 with different allowedIp definitions (and i guess also an additional wg-portal instance?)

Concept/Design B "per client limitation":

IMHO this would need a different API, also given the clients individual AllowedIP rules and then creating FORWARD rules for the client tunneIP, not for all clients to the outgoing allowedIp list for this specific client. Possible but for sure way more effort then A and maybe way to off-grid for the usual use-case for wireguard.

EugenMayer commented 3 years ago

As i learned, wg-portal already includes multiple interface support, so one wg-portal can maintain several wg instances on one server, i really can only see A as a good option.

We did exactly that, using custom / own shorewall rules to define which network the wg interface can forward to, thus we create different limitations. Works well and is guarded by a battle proven IPtables concept without layers. Find this rather appealing.

paulignari commented 1 year ago

Concept/Design B "per client limitation":

Just to add some food for thought I think that most of the info for the Concept/Design B "per client limitation" are already on the db:

select ips_str, allowed_ips_str, allowed_ips_srv_str from peers limit 2;
+-------------------------------------------+------------------------------------------+---------------------+
| ips_str                                   | allowed_ips_str                          | allowed_ips_srv_str |
--------------------------------------------+------------------------------------------+---------------------+
| 172.16.2.33/32                            | 192.168.1.0/24, 10.0.0.0/16              |                     |
| 172.16.2.4/32, fddc:6585:aedb:3232::4/128 | 192.168.3.0/24, fddc:4f58:e4a2:2233::/52 |                     |
+-------------------------------------------+------------------------------------------+---------------------+

The ips_str syntax (comma separated values) is the same of nftables sets while some effort is needed to separate ipv4 and ipv6 address. A oversimplified rule can be one like this:

nft add rule inet filter forward ip saddr { $ips_str_ipv4 , $allowed_ips_srv_str_ipv4} ip daddr {  $allowed_ips_str_ipv4 }
 accept 
nft add rule inet filter forward ip6 saddr { $ips_str_ipv6 , $allowed_ips_srv_str_ipv6} ip daddr {  $allowed_ips_str_ipv6 }
 accept 

I was tempted to generate a similar config with a crontab but a more efficient approach is to detect configuration changes and update the firewall config, triggering a rules reload (in issue #142 gudata suggest to use systemd.path for similar job).

Concept/Design C "per group limitation":

A thing I really miss in wg-portal is method to define common properties for users, something like groups or templates.

Now every users has his allowed_ips, if we add a db server we need to examine every peer to see if it needs to be updated with the new ip, and the user must re-download (or manually change) his config . Using a "group" o "template" feature, changing the template automatically updates every user belonging to it, but the user still needs to e-download (or manually change) his config. If the "group" o "template" can handle the firewall rules too, we can leave the allowed_ips quite permissive and restrict access with nftables or iptables (the first better). I know this is a big change and maybe needs a dedicated issue, I put it here just to add another option, so I don't dig deeper without a feedback