How to setup multiple tunnels with ProtonVPN and have remote access via Wireguad

Started by ttfzi, March 30, 2025, 03:53:46 PM

Previous topic - Next topic
A step-by-step guide on how to set up multiple tunnels with ProtonVPN and have remote access via Wireguard at the same time. And it really works.

A few words to start with.
I have a remote device with which I access my home services (NAS, home Nextcloud server, etc.). I have Opnsense as a router/firewall at home. I decided to subscribe to ProtonVPN a few days ago and connect to Opnsense using wireguard. If I use the ProtonVPN app on the remote device, the services at home are not accessible. If I connect to home, the connection to ProtonVPN does not work. The logical step was to set up another wireguard tunnel on Opnsense and connect the remote device to ProtonVPN through it.
In addition, I wanted to use more tunnels on ProtonVPN, for example, one to Albania, another to the USA, and a third to Switzerland, connecting individual devices to different tunnels and connecting other devices to the Internet directly via the ISP. Unfortunately, despite all my efforts, I was unable to get the tunnels to ProtonVPN working. I followed the instructions found on internet, but the hosts were still without an Internet connection. I checked the settings again and again and was desperate. I was about to give up. But then I came up with a solution. And maybe I even figured out the reason why it didn't work (I'll explain later). I would like to share with you the procedure for having several tunnels to ProtonVPN and another for remote connections.

Disclaimer:
If you follow this guide, you do so at your own discretion and I am not responsible for any damage or injury that may occur to anyone using this guide, in any way and under any circumstances. The guide is written in good faith and without malicious intent.

Warning: Read the entire guide carefully, point by point, before you do anything to make sure you understand everything and are able to handle the steps it contains. And one more important thing before you start. Backup. BACKUP. BACKUP! There's nothing worse than messing something up and ending up with a broken Opnsense without internet access. In Opnsense go to System>Configuration>Backups and make backup. Just to be safe, also download the latest Opnsense installation in case something really goes wrong and you have to restore the installation.

We have this goal:

Remote device(s) > wireguard > encrypted connection thru internet to Opnsense > access to home services > from Opnsense access to the internet via ProtonVPN.

Additionally: both home and remote devices should have access to multiple ProtonVPN tunnels running simultaneously, with Opnsense allowing you to select which devices will use which tunnel.

1. What we will need:

1.1. A working Opnsense with a public IP address (for connecting of the remote device to Opnsense).

1.2. A PC on the local network from which we will configure Opnsense and wireguard tunnels.

1.2. Another computer/server/virtual machine connected on the local network for installing Ubuntu server (no real PC needed, a VM is more than enough). Currently installed Ubuntu on PC will also do, but I recommend to use fresh and dedicated installation.

1.3. Somewhat advanced experience using the Ubuntu Linux command line and knowledge of configuring Opnsense.

1.4. A ProtonVPN plus subscription or higher (to be able to create tunnels).

If you don't have any of the above, I'm afraid this guide won't help you.

Let's go.

2. Prerequisites:

2.1. In the guide, I will assume that wireguard is installed and running on Opnsense, that the tunnel for connecting the remote device via wireguard is already working (for instructions, find How to use wireguard to connect remotely to your home network on the Internet), and that the wireguard subnet is 10.0.0.0/24 (Opnsense end of tunnel is on IP 10.0.0.1, remote host is on IP 10.0.0.2). I also assume that the interface for wireguard is OPT1. These IP addresses have nothing to do with the IP addresses of ProtonVPN tunnels. The only thing they have in common is that they are both local IPs.

2.2. I further assume that the LAN interface on Opnsense has subnet 192.168.1.0/24 and that the LAN IP address of Opnsense is 192.168.1.1.

2.3. Again, I assume that the PC from which Opnsense and wg-server will be configured has the IP address 192.168.1.2, it runs Ubuntu desktop, and the terminal with ssh client is available on it. Your actual IP addresses will likely be different. Replace them with your actual IP addresses in the commands in the guide. Ubuntu desktop is not really necessary, but that's how I do it. However, it is important to be able to connect to the wg-server via ssh. So if I continue to use "open a terminal", "use the scp command", "use ssh..." in the text, I am doing it from Ubuntu desktop. If you are using another operating system, you will have to deal with ssh as you know how, that is beyond the scope of this guide.
2.4. In the guide, in addition to IP addresses, I will use the following for simplicity: Opnsense for configured router (192.168.1.1), wg-server for computer/VM where tunnels will be running (in section 3.2. it will be assigned the address 192.168.1.100) and PC for computer from which the configuration will be done (192.168.1.2).

3. Prepare wg-server for wireguard routing:

3.1. Download Ubuntu server distribution from official web pages and start installation (instructions how to do this can be found on internet). If you are installing on a virtual machine, don't forget to add a network card. You need to set up the virtual network card so that the guest can get an IP address from Opnsense's DHCP server in the same subnet, i.e. 192.168.1.0/24.

3.2. During installation, choose to automatically configure the network interface using DHCP. Let's say the DHCP server on Opnsense assigned the IP address 192.168.1.100 to the wg-server.

3.3. During installation, choose to install the openssh server for easy configuration via SSH. Enable password login. You can later strengthen security as desired.

3.4. Next, during installation, create a user account, in this guide it is called wg.

3.5. After the installation is complete, reboot and log in to wg-server and install wireguard, ufw (Ubuntu firewall), and nano.

$ sudo apt install wireguard ufw nano

Make sure that IP forwarding is enabled:

$ cat /proc/sys/net/ipv4/ip_forward

If  answer is 1 you have to do nothing. If answer is 0 you have to edit config file in order to enable it:

$ sudo nano /etc/sysctl.conf

In nano editor find line starting with net.ipv4.ip_forward and edit it like this:

net.ipv4.ip_forward = 1

Save it (ctrl-o) and exit nano (ctrl-x)

Next, allow port 22 for incoming traffic at least from PC:

$ sudo ufw allow from 192.168.1.2 to any port 22 proto tcp

Enable ufw:

$ sudo ufw enable

In order to wireguard traffic routing to be working, change default ufw routed policy:

$ sudo ufw default allow routed

Check if ufw is working and port 22/tcp is allowed:

$ sudo ufw status verbose

3.6. Reboot wg-server.

4. Get the configuration file(s) for tunnel(s) from ProtonVPN:

4.1. On PC open web browser and login to ProtonVPN (protonvpn.com).

4.2. From menu on the left side choose Download.

4.3. On Download page scroll down to Wireguard section.

4.4. Name the tunnel whatever you want, the name is only important for tunnel management on this page, we will rename the downloaded file later anyway. I named it wg0 (later another wg1, etc.) On platform selection choose GNU/Linux. In the VPN options, under Level for NetShield blocker filtering, choose what suits you, I chose Block malware, ads and trackers. Why not have an ad blocker with your VPN, right? But it's up to you. From the options below, select only VPN accelerator, nothing more. Further down, select a country and a specific server and click create.

4.5. IMPORTANT STEP: When the configuration file appears on the screen, click Download. If you close the window without downloading, the important PrivateKey will no longer be visible and the tunnel will be useless to you. You will need to remove it from the list of tunnels above and create it again. Save the file somewhere, (I recommend to create new folder for it, e.g. ProtonVPN) and name it wg0.conf (the next config file name wg1.conf, etc.).

4.6. Repeat the steps in sections 4.4 and 4.5 to get more tunnels if you want. I created three.

5. Create tunnels on wg-server:

5.1. On PC open file manager, navigate to folder with downloaded config files (in this guide ProtonVPN) and open terminal on that folder (if you are using Ubuntu, in the directory right-click and select Open in Terminal). The terminal will open. If you do not using Ubuntu desktop, open the terminal on your desktop and navigate to folder where config files are saved manualy.

5.2. Copy the configuration files to wg-server:

$ scp ./*.conf wg@192.168.1.100:/home/wg/

Confirm that you accept the new fingerprint and enter the password created when you created the wg user account on the wg-server. Config files will be copied to /home/wg directory of wg-server.

Connect to wg-server using ssh:

$ ssh wg@192.168.1.100

While connected, move the files from /home/wg to the /etc/wireguard directory:

$ sudo mv /home/wg/*.conf /etc/wireguard/

When prompted for a password, enter the password for user wg. The configuration files are now moved where they belong.

5.3. Edit the configuration file. AND HERE COMES THE MAGIC! I'll explain what the magic is later.

$ sudo nano /etc/wireguard/wg0.conf

Edit the file as follows. Create the lines that are missing in your file:
___________
[Interface]
# Key for wg0
# Bouncing = 0
# NetShield = 2
# Moderate NAT = off
# NAT-PMP (Port Forwarding) = off
# VPN Accelerator = on
Table = 2200
PostUp = ufw allow from 192.168.1.200/32
PostUp = ip -4 rule add from 192.168.1.200/32 table 2200
PostDown = ufw delete allow from 192.168.1.200/32
PostDown = ip -4 rule del from 192.168.1.200/32 table 2200
PrivateKey = here is your private key
Address = 10.2.0.2/32
DNS = 10.2.0.1

[Peer]
# AL#37
PublicKey = here is your key
AllowedIPs = 0.0.0.0/0
Endpoint = 31.171.153.98:51820
PersistentKeepalive = 25
________

The characters ________ do not belong in the configuration file, they only separate it from the guide text.

Line by line explanation:

[Interface] part:

Lines starting with # are just comments.

Table = 2200 - This tells the system that a special routing table will be created for this tunnel. The number 2200 is not important, you can use another one, but it must match the number in the next lines.

PostUp = ufw allow from 192.168.1.200/32 - This line will create a ufw rule when the tunnel is  up, allowing incoming traffic from IP 192.168.1.200. Remember this address, it will be important in part 6.

PostUp = ip -4 rule add from 192.168.1.200/32 table 2200 - This is the most important line of all. It tells WireGuard to only route traffic coming from IP 192.168.1.200 into the tunnel. Outgoing traffic going to destination addresses allowed in the AllowedIPs line will be routed into the tunnel. The information with this instruction is stored in the routing table 2200 that was just created.

Note:
Normally, wireguard creates routing instructions that allow the system to route outgoing traffic from any source address to the tunnel, but only for the destination addresses specified in AllowedIPs. For example, if only the address 8.8.8.8/32 were allowed in AllowedIPs, all network traffic that had a source on the vg-server or came here from outside and was intended for the destination address 8.8.8.8 would be routed to the tunnel, and outgoing traffic for other IP addresses would be routed through the default gateway, in our guide through 192.168.1.1. When the address 0.0.0.0/0 is specified in AllowedIPs, without the above routing instruction, ALL network traffic that had a source on the vg-server or came here from outside would be routed to the tunnel, with ANY destination IP address. A conflict would occur when creating another tunnel with AllowedIPs = 0.0.0.0/0.  The system would not know which tunnel to route all outgoing traffic to, it would send it to the first tunnel anyway, or no outgoing traffic would go anywhere. This default behavior of wireguard when routing network traffic from all source addresses is, in my opinion, responsible for why it is not possible to set up multiple tunnels directly on Opnsense without any problems. The setting for selective routing of source addresses in the Opnsense's wireguard implementation is missing there. But I don't know for sure, I could be wrong. But back to the configuration file:

PostDown = ufw delete allow from 192.168.1.200/32
PostDown = ip -4 rule del from 192.168.1.200/32 table 2200 - These two lines remove the ufw rule allowing incoming traffic from the address 192.168.1.200 and cancel the routing from this address to the tunnel when the tunnel is down.It is a good idea, although not necessary, to remove routing and firewall rules when the tunnel is not running, for security reasons and to prevent unforeseen routing problems.

PrivateKey = here is your private key - The private key is used to encrypt outgoing packets. Do not change the line.
Address = 10.2.0.2/32
DNS = 10.2.0.1 - These lines are used to set the IP address of the tunnel entry on our side, and the DNS server address on the ProtonVPN side. Note the addresses 10.2.0.1 and 10.2.0.2/32. We will not change them now, but we will in other configuration files. I will explain later.

[Peer] part:
# AL#37 - comment. It can help us identify the geographical exit location of the tunnel - see the end of this section 5.
PublicKey = here is your key - The public key is used to decrypt incoming packets. Do not change the line.

AllowedIPs = 0.0.0.0/0 - This line was explained above. It specifies which destination IP addresses should be routed into the tunnel. In short: the number after the slash indicates the subnet. The IP address 0.0.0.0/0 is a special IP address that simply means "all IP addresses in all possible subnets".

Endpoint = 31.171.153.98:51820 - The IP address on the internet where the ProtonVPN tunnel server is located. The number after the colon is the port number. Do not change the line.

PersistentKeepalive = 25 - The last but important line. It tells WireGuard to send an empty encrypted packet through the tunnel every 25 seconds, which means something like "Hello, I'm here, the tunnel is working, I'm not lost anywhere." This is very important because the UDP protocol used by WireGuard does not have any self-healing mechanisms, like TCP in OpenVPN. The connection via UDP is faster, but more fragile. (I don't want to make you worry that WireGuard is not secure. The fragility lies only in the UDP protocol communication between devices, not in the vulnerability of encrypted transmission. WireGuard is secure.) In addition, WireGuard does not normally maintain a permanent connection with the server on the other side - no data needs to be transferred? Okay, nothing is transferred. This is a safe and economical approach, but it leads to the server on the other side being able to (and does) close the communication port and release it for other connections. Something like "They haven't heard from us for a long time, who knows if they'll ever hear from us again, we won't wait any longer..." If the port is closed and released, it will no longer respond to incoming connections from our side, even if they are properly encrypted. Something like "the letter arrived here, the address matches, but the recipient has already moved away". Then the tunnel must be terminated and restarted to restore the connection. Sometimes it is even necessary to restart wg-server. PersistentKeepalive = 25 prevents the tunnel from being "staled" unintentionally. Do not change the interval or remove the line.

Save the file and exit nano (ctrl-o, ctrl-x).

5.4. If you have created more tunnels edit next config file, in our case wg1.conf:

$ nano /etc/wireguard/wg1.conf.

We will add the Table, PostUp, PostDown, and PersistentKeepalive rows again. However, we will change some of the numbers, including some of the existing rows. In the [Interface] part:


Table = 2201
PostUp = ufw allow from 192.168.1.201/32
PostUp = ip -4 rule add from 192.168.1.201/32 table 2201
PostDown = ufw delete allow from 192.168.1.201/32
PostDown = ip -4 rule del from 192.168.1.201/32 table 2201
Address = 10.3.0.2/32
DNS = 10.3.0.1

And in the [Peer] part we only add:

PersistentKeepalive = 25

Leave all other lines in both parts as they are, do not change them, do not delete them. Save the file and rxit nano.

Explanation:
In the Table line, we increase the table number by one, i.e. to 2201, so that a separate table is created and not written to the same table 2200, as in wg0.

In the PostUp and PostDown lines, we also increase the last number of the IP address by one, to 192.168.1.201/32, so that WireGuard knows from which specific hosts traffic should be routed to which specific tunnel and for ufw to allow traffic from this address. In lines where there is a table at the end, we also change the table number to 2201 so that the routing instruction is written to this table. I will explain addresses 192.168.200/32, 192.168.1.201/32... in more detail in the next section.

In the Address and DNS lines, we increase the second number in the IP address by one, i.e. to 10.3.0.2/32 and 10.3.0.1, because each tunnel must have its own IP address and DNS, otherwise the tunnel would not be able to be created. Changing the IP address in its second number and not, let's say, in the third is the result of my communication with ProtonVPN support on how to create multiple tunnels.

In the [Peer] part the PersistentKeepalive setting remains the same for all created tunnels. The meaning of the line is explained above.

5.5. We proceed with all other configuration files for tunnels according to point 5.4, adjusting the numbers accordingly.

5.6. Start the tunnels:

$ sudo wg-quick up wg0
$ sudo wg-quick up wg1

... and so on with all the other tunnels. If an error message appears when you start it, you wrote something wrong in the configuration file. Please check the configuration file again carefully and correct the errors.

Check if the tunnels are running:

$ sudo wg

All running tunnels should appear in the listing. In the latest handshake section, we can see that the tunnels are actually running and connected to ProtonVPN. Next, we check if incoming traffic from IP addresses 192.168.1.200 192.168.1.201... is allowed in ufw:

$ sudo ufw status verbose

The addresses should be listed in the from column.

5.7. Now we need to ensure that the tunnels survive a possible restart of the wg-server:

$ sudo systemctl enable wg-quick@wg0

$ sudo systemctl enable wg-quick@wg1

... and so on with all the other tunnels.

We are done with the wg-server, in the next part we will configure Opnsense. But before you do that, make a note of for which tunnel you allowed which IP address in PostUp - e.g. "For the tunnel to Albania (configuration file wg0.conf), I allowed traffic from IP address 192.168.1.200.". Make a note of this for all tunnels you have created. To see config files you can use cat command:

$ sudo cat /etc/wireguard/wg0.conf
$ sudo cat /etc/wireguard/wg1.conf

...and so on.

6. Configure Opnsense to send traffic to wg-server. The magic continues.

6.0. I mentioned this in the introduction. In case you missed it, I strongly recommend it again: MAKE A BACKUP OF YOUR Opnsense SETTINGS!
  a. Login to Opnsense
  b. Go to System>Configuration>Backups
  c. In the Download section, leave all unchecked and click Download configuration button

6.1. Login to Opnsense as admin if you are not logged in already.

6.2. First we need to provide a static DHCP mapping for wg-server:
  a. Go to Services>ISC DHCPv4>Leases.
  b. Find IP address of wg-server on the list (192.168.1.100 in this guide)
  c. Click the + button on the right side of the line with the wg-server IP address.
  d. Fill window as follows:
    MAC address - leave it as it is
    Client identifier - wg-server
    IP address - 192.168.1.100 (this is correct in this guide, it will probably be different for you)
    Hostname - wg-server
    Description - fill in if you wish
    ARP Table Static Entry - unchecked
  Leave the rest of the fields as they are.
  e. Click Save.
  f. Click Apply changes.
This step is important so that the DHCP server on Opnsense does not assign a different IP address to the wg-server later.

6.3. Create virtual IPs for the tunnels:

Note:
Virtual IP addresses are a much-overlooked and misunderstood, yet powerful tool. They can help us set up special rules for certain parts of a subnet (firewall rules, NAT rules, routing) without affecting the behavior of the entire subnet. In this guide, virtual IP addresses will help us distinguish and correctly direct traffic from individual hosts to individual tunnels.

  a. Go to Interfaces>Virtual IPs>Settings
  b. Click on + button
  c. Fill the settings as follows:
    Mode: IP Alias
    Interface: choose the interface on which is wg-server is assigned (in this guide it is LAN)
    Network / Address - 192.168.1.200/32 (the subnet after the slash specifies that it is just one IP address and not a range of addresses)
    Description - fill in if you wish. I recommend that you enter the geographical location of the tunnel in the Description, which you noted in the previous section, for example Albania_ProtonVPN
    Leave the rest of the fields as they are.
  d. Click Save
  e. Click Apply

6.4. Repeat point 6.3. for all other tunnels. Always increment the last number in the IP address, similar to point 5.3.

6.5. Create firewall aliases for host groups for different tunnels:
  a. Go to Firewall>Aliases
  b. Click to + button
  c. Fill in the window as follows:
    Enabled - checked
    Name - Name the alias, preferably in a way that tells you which tunnel the traffic will be intended for, for example wg0_Albania
    Type - Host(s)
    Categories - leave blank
    Content - Here, enter the IP addresses of all hosts that we want to route to the wg0 tunnel. There can be one or more hosts, they can be from different local or VPN subnets. For example, we will add the IP address 10.0.0.2 here, which is the remote device mentioned in point 2.1. That's what's great about aliases, that they can group IP addresses from different subnets and a single NAT and firewall rule can be applied to them.
    Statistics - unchecked
    Description - fill in if you wish
  d. Click to Save.
  e. Click to Apply

6.6. In a similar way, create as many firewall aliases as you need for the various device groups you create, e.g. wg1_USA, wg2_Switzerland, etc. and add hosts to them whose traffic should be routed to the corresponding tunnels. In our guide, we will assign the IP address of the PC (192.168.1.2) to the alias wg1_USA. But remember that none of these aliases may contain a host that you have already specified in another alias. For example, host 192.168.1.2 (PC) may not be in both the alias wg0_Albania and the alias wg1_USA. It can only be in one or the other. Or, in other words, you CAN actually add hosts to multiple aliases, but it won't do you any good. If you do so, the firewall will still send traffic only to the tunnel for which the first floating rule in the sequence will be processed. We will create floating rules in section 6.9. Therefore, it is better to keep your aliases organized and, if you add a host to a different alias than it was originally, remove it from the original one.

6.7. create one more special alias for local subnets, which we will use later in firewall and NAT rules:
  a.  Go to Firewall>Aliases (if you are not there already)
  b. Click to + button
  c. Fill in the window as follows:
    Enabled - checked
    Name - local_subnets
    Type - Network(s)
    Categories - leave blank
    Content - Enter the IP ranges of all local networks here. Note that I am not writing the IP addresses because these are entire subnets, so the number after the slash will be 24, so in this guide there will be addresses 192.168.1.0/24 and 10.0.0.0/24. The last number in the IP addresses, 0, is fine because this is an entire subnet. It simply means "all IP addresses in the /24 subnet range", so for example, for subnet 192.168.1.0/24 this means all IP addresses 192.168.1.1 to 192.168.1.255. Do not enter any tunnel ranges created on the wg-server for ProtonVPN (e.g. 10.2.0.0/24) here! They do not belong here and are also unknown to Opnsense, they only make sense to the wg-server itself. If you have multiple local subnets, such as 192.168 2.0/24, enter them here instead.
    Statistics - unchecked
    Description - fill in if you wish
  d. Click to Save.
  e. Click to Apply.

6.8. Create gateway for wg-server:

Note:
Gateways are usually outgoing addresses for network traffic. When your computer is connected to a certain subnet (for example 192.168.1.0/24), it must know not only its own IP address (for example 192.168.1.2/32), but also the IP address of the computer or router where it should route outgoing traffic (in the guide, the PC routes outgoing traffic to Opnsense to the address 192.168.1.1). This IP address is therefore the gateway for the PC. But bear in mind: Every computer or network device connected to Opnsense in our guide must have a gateway set, but this does not mean that the gateway IP address must always be the SAME. For example, a remote device connected to Opnsense via wireguard has a gateway set to 10.0.0.1/32 when operating in a tunnel to Opnsense. Routers in particular can have multiple gateways to properly route outgoing traffic to different networks. In this case, one gateway is always the default. In Opnsense, the default gateway is usually set to the IP address of your Internet Service Provider, or ISP. However, we will create a gateway to an address on the LAN network, and then we will route traffic intended for ProtonVPN tunnels to it.

  a. Go to system>Gateways>Configuration
  b. Click on + button
  c. Fill in the window as follows:
    Disabled - unchecked
    Name - wg-server
    Description - as always at this point
    Interface - From the drop-down menu, select the interface to which the wg-server IP address is assigned, in this guide it is LAN
    Address Family - select IPv4
    IP Address - fill IP address of wg-server (in this guide 192.168.1.100)
    Upstream Gateway - unchecked
    Far Gateway - unchecked
    Disable Gateway Monitoring - unchecked
    Monitor IP - leave empty, let Opnsense take care of it itself
    Mark Gateway as Down - unchecked
    Priority - leave it as it is
  d. Click to Save.
  e. Click to Apply.

This section is so long, isn't it? But don't worry, we're almost there.

6.9. We will create a firewall rule that will first allow traffic to the wg-server, secondly ensure that only traffic from hosts where we want it will be redirected (remember firewall aliases?), thirdly ensure that traffic intended for local networks will not be sent to the tunnel (remember firewall alias "local_subnets"?), and fourthly send the correct traffic to the wg-server gateway. Cool, huh? So let's get started:
  a. Go to Firewall>Rules>Floating

Note: (Oh no, again? Yes, again!)
It often happens that users do not use floating firewall rules and prefer to stick to rules for individual interfaces. And yet floating rules are so useful. First of all, floating rules are processed before rules for Interfaces, but most importantly, these rules can be used for multiple interfaces at once. In our case, it is even necessary, because hosts from aliases that we created in point 6.5. can be located in different subnets and therefore the firewall rule must include all these interfaces (in this guide, this is the case - the remote device falls under the wireguard interface OPT1, the PC under the LAN interface).

  b. Click + button
  c. Fill the settings as follows:
    Action - Pass
    Disabled - unchecked
    Quick - checked
    Interface / Invert - unchecked
    Interface - From the drop-down menu, select all local network interfaces, in our guide these are OPT1 for wireguard and LAN for lan. This is so that the rule applies to all hosts added to aliases on any of your local networks.
    Direction - in
    TCP/IP Version - IPv4
    Protocol - any
    Source / Invert - unchecked
    Source - in the drop-down menu, find and select the alias you created in point 6.5., in our guide it is wg0_Albania
    Destination / Invert - CHECKED
    Destination - the drop-down menu, find and select the special alias you created in point 6.7., in our guide it is local_subnets
    Destination port range - any in both fields
    Log - unchecked
    Category - leave empty
    Description - if you wish...
    No XMLRPC Sync - unchecked
    Schedule - none
    Gateway - in the drop-down menu, find and select the gateway you created in section 6.8., in our guide it is wg-server - 192.168.1.100
    Rest of the fields leave as they are
  d. Click to Save.
  e. Click to Apply changes

6.10. Create similar rules for all other tunnels in the same way. The only item that will change in the rules is the Source item, in which you select the other aliases you created. If you want, for creation of another rules you can use the Clone button on the right side of the row with the finished rule and then just select another alias in the Source item.

Are we done yet? Not quite. If we finished now, the traffic would still go to the wg-server, but the wg-server would throw it all away and not send it anywhere else. Why? Because the packets would go to the wg-server with the original source IP address, i.e. 10.0.0.2, 192.168.1.2... The result would be that all hosts selected for ProtonVPN tunnels using the created aliases would only have access to the local network, but not to the Internet. If you want, you can check it. You are in this situation right now. If you have added the computer from which you are currently configuring Opnsense to one of the aliases (in our guide it is PC - 192.168 1 2), enter for example www.google.com in the browser. You will get a notification that the page was not found. And that's why we need another, final step.

6.11. Create an outbound NAT rule:
  a. Go to Firewall>NAT>Outbound (There won't be any notes? There won't be, really not anymore.)
  b. If the "Hybrid outbound NAT rule generation (automatically generated rules are applied after manual rules)" option is not selected in the Mode section at the top, select it and click Save
  c. At the bottom, tap the + button
  d. Fill in the window as follows:
    Disabled - unchecked
    Do not NAT - unchecked
    Interface - select the interface to which wg-server is assigned, in our guide it is LAN
    TCP/IP Version - IPv4
    Protocol - any
    Source invert - unchecked
    Source address - here we will again select aliases for individual tunnels from the drop-down menu, just like in point 6.9. in the Source item, e.g. we will start with wg0_Albania
    Source port - any
    Destination invert - UNCHECKED
    Destination address - any
    Destination port - any
    Translation / target - here from the drop-down menu we select the virtual IP that we created in points 6.3. and 6.4. And again: the IP address must match the one from the configuration file that we processed on the wg-server in points 5.3. and 5.4. Use the notes you made at the end of Section 5. ilIn this guide it is 192.168.1.200 (AL_ProtonVPN)
    Log - unchecked
    Translation / port - leave empty
    Static-port - unchecked
    Pool Options - default
    Set local tag - leave empty
    Match local tag - leave empty
    No XMLRPC Sync - unchecked
    Category - leave empty
    Description - here I recommend that you write something that reminds you which tunnel the rule is for, e.g. "Albania"
  e. Click Save.
  f. Click Apply changes.

6.12. Repeat the steps in section 6.11. one by one for all aliases and corresponding virtual IPs. Use the notes from the end of section 5.

6.13. Now the hosts from each alias should have access to the internet via ProtonVPN tunnels running on the wg-server. If you later want to move a host to another tunnel, just delete its IP address from the firewall alias in Firewall>Aliases, add it to another alias and save the changes, nothing more.

7. The seventh day is usually a day of rest, the seventh part is also pleasant. Enjoy surfing the Internet without ads with ProtonVPN. And if your remote devices are connected via your own wireguard tunnel to your Opnsense, you can use the benefits of ProtonVPN on them too.

Conclusion
Before I came up with this solution, I read a lot of guides, both on this forum and elsewhere on the internet. I put together guides on ProtonVPN, Opnsense, wireguard, network routing... Some of them didn't work for me, but they all inspired me. Even though I didn't mention these sources in the guide, I would like to thank everyone in this way. I tried to write the guide in sufficient detail, clearly and to explain everything important as much as possible. Of course, it may seem too wordy to some, but I believe that it is better to read longer and understand things than to just blindly follow some short instructions and not know what I am doing and why.
And finally, a warning. Even though I have checked this guide several times for errors and I believe there are none, there is always a chance that I have missed something. Therefore, I ask all those who are experts in solving the problem to point out any errors to me so that I can fix them. I hope this guide helps someone with a similar problem as I had.

Have a good time.