There are many ways to bypass blocking sites and ensure online privacy. Terms like TOR, VPN, and proxy are well-known. You don't need any special knowledge to connect and configure them, but there are also more elegant solutions. Today I will talk about the method of bypassing locks in Linux with traffic masking and show you several scripts for automating this. They can be easily transferred to the Raspberry Pi to make a smart router.
This article is not a guide. It is written solely for the purpose of introducing you to some routing functionality on Linux systems. Author of the article and site editors www.spy-soft.net they do not bear any responsibility for the result of using the methods and techniques described here.
Linux provides a huge set of routing features and configuration tools. Experienced sysadmins know this and use the Linux Arsenal to the fullest. But even many advanced users do not realize how much convenience all these wonderful features can bring. Today we will create routing tables and describe the rules for passing through them, as well as automate the administration of these tables. So, our creative plans:
Traffic encryption in Linux
What will we need to make everything work, and preferably comfortable? Of course, iptables, where without it. Another iproute2, it will allow us to create a bunch of tables. IPSet is required in order not to make a garden out of a set of iptables rules.
What is what
Briefly about two options
The client and server will establish an encrypted communication channel on port 443 (stunnel) and transmit inside OpenVPN on port 995th. From the outside, it should look like regular HTTPS
Illustration of how stunnel + OpenVPN works
And here you can implement two connection schemes.
Option 1. On the client machine, iptables will mark packets with a certain flag if the addresses in the packets and IPSet lists match, and pass them for routing.
Next, the packets marked with this flag will be sent using a pre-created routing table, while the rest will follow the default route. We will use the console or a small script to correct this list of addresses. Depending on the situation, there may be several lists.
Option 2. The client will be a host on the local network (a virtual machine, Raspberry Pi, or some other device). It will be specified as the primary gateway on computers that need to access resources via VPN. After receiving a request for an IP address from the list, the gateway will enable NAT and send such traffic to the VPN. The rest of the traffic will be routed to the default gateway without NAT.
For Linux systems, we can leave the default gateway and set IPSet and iproute2, and then configure them in the same way as the settings of the "intermediate" host router. In this case, at the client level, traffic will be selected using the same IPSet list. That is, what is in the list will be sent to the intermediate host router and then to the VPN. The rest will be routed by default.
Implementation
Let's assume that somewhere far away in the cloud, we already have a VPS server running Ubuntu or Debian. In other distributions, the differences will most likely only be in the installation of the necessary packages. This host will be used as a VPN server in our configuration. There are plenty of recommendations on which VPS is best to use on the Internet for different budgets, with different configurations and conditions.
Install OpenVPN, stunnel, and git on the server:
Next, we will use a ready-made script to configure the OpenVPN server. You can, of course, configure everything manually, and I advise you to do just that. Information on how to properly configure OpenVPN is easy to find on the Web. But if you need to get the result very quickly and you don't want to mess around, then here's a quick solution.
We get the installation script and run it. It will help you create custom keys and certificates, and if necessary, change the network address. Everything is very accessible and clear. At the output, we will get one file for each user, inside which there will be a configuration key and certificates (server and user). Passing this file to the client.
Open the OpenVPN server configuration file and edit it. Select the appropriate port the one that will be available for connection on the server. It is better to use a more or less inconspicuous port (I chose 995, usually mail ports are left open), so that the client can be guaranteed to connect to the VPN server.
Here's what our config will look like:
The next step is to set up stunnel:
Everything is simple here:
Generating keys and certificates for stunnel:
At this stage, it is important to remember that we have OpenVPN on port 995 proto tcp, dev tun0 and stunnel on port 443 running on the server side. All other settings are standard.
Going to the client:
Everything you need has been set up, and now we are configuring stunnel on the client side:
Here we specify where to output logs, client mode is enabled. Using the accept Directive, we tell you which address and port to send the connection to and where the stunnel client should actually connect (the connect option). Well, which certificate to use.
Passing the OpenVPN client file from the server. We check the settings: port 995, proto tcp, dev tun0 is used. A very important point: we need to declare a route to our VPS through the default gateway. Otherwise, stunnel will establish a connection, then the VPN will connect and try to redirect everything to the tunnel, but stunnel will no longer be able to work, since the host and port will be unavailable. We also disable redirection of all traffic to the VPN, check the connection address and port. The address of the VPN server in the config will be 127.0.0.1 — that is, localhost. It is assumed that stunnel has already forwarded the required client port. You should get something like the following:
So, OpenVPN and stunnel are installed and configured on the server and client. Secure connection is established. Next, we will consider each option in turn.
Option 1: VPN client on the user's machine
First of all, we will create a list of IP addresses that we will use next:
Adding a single test address to it:
Now we need to label packets with destination addresses that match the list.
As a result of our actions, iptables will start marking such traffic if the destination address matches the address from The ipset list. Next, we will create a new routing table. to do this, we will write it in the /etc/iproute2/rt_tables file with a priority higher than default (253):
Now you need to create a rule and route for labeled packets.
Don't forget to enable itrp_filter
to ensure asymmetric routing, we also allow packet forwarding between interfaces, in case someone needs to grant access to private resources on the local network.
Now enable NAT for traffic that is routed to the VPN.
If you need to provide access from the local network via your VPN, the iptables rule needs to be slightly tweaked, namely transferred to another chain.
As a result, we get that all addresses from The ipset VPN list go through a secure connection, while the rest are routed through the default route.
Thank you all for your attention!
This article is not a guide. It is written solely for the purpose of introducing you to some routing functionality on Linux systems. Author of the article and site editors www.spy-soft.net they do not bear any responsibility for the result of using the methods and techniques described here.
Linux provides a huge set of routing features and configuration tools. Experienced sysadmins know this and use the Linux Arsenal to the fullest. But even many advanced users do not realize how much convenience all these wonderful features can bring. Today we will create routing tables and describe the rules for passing through them, as well as automate the administration of these tables. So, our creative plans:
- let's decide what we need: install the necessary packages and find out why they are needed;
- let's study the General principle of the bundle's operation;
- setting up a secure VPN channel using OpenVPN + stunnel;
- let's make lists of addresses and describe their application areas;
- creating a script for quickly adding a domain or IP address to IPSet lists, adding it to the routing table and including it in the redirect rules;
- we use SSH to provide a secure communication channel to these of your Internets.
Traffic encryption in Linux
What will we need to make everything work, and preferably comfortable? Of course, iptables, where without it. Another iproute2, it will allow us to create a bunch of tables. IPSet is required in order not to make a garden out of a set of iptables rules.
What is what
- iptables is a command-line utility. Basic firewall management tool for Linux kernels.
- iproute2 is a set of utilities for managing network device parameters in the Linux kernel.
- IPSet-a tool for working with lists of IP addresses and network ports in a network filter. Generates a list in a special format for transmission to the firewall.
- stunnel is a tool for organizing encrypted connections for clients or servers that do not support TLS or SSL. Stunnel intercepts unencrypted data that should have been sent to the network and encrypts it. The program works on both Unix and Windows systems. As encryption, it uses OpenSSL to implement the basic TLS and SSL Protocol.
- OpenVPN-a VPN server that supports encryption using the OpenSSL library. Client parts are available on almost all platforms. It can work through proxies such as Socks, HTTP, NAT, and network filters.
Briefly about two options
The client and server will establish an encrypted communication channel on port 443 (stunnel) and transmit inside OpenVPN on port 995th. From the outside, it should look like regular HTTPS
![46d70fda120c47a9b4245.png](https://telegra.ph/file/46d70fda120c47a9b4245.png)
Illustration of how stunnel + OpenVPN works
And here you can implement two connection schemes.
Option 1. On the client machine, iptables will mark packets with a certain flag if the addresses in the packets and IPSet lists match, and pass them for routing.
Next, the packets marked with this flag will be sent using a pre-created routing table, while the rest will follow the default route. We will use the console or a small script to correct this list of addresses. Depending on the situation, there may be several lists.
Option 2. The client will be a host on the local network (a virtual machine, Raspberry Pi, or some other device). It will be specified as the primary gateway on computers that need to access resources via VPN. After receiving a request for an IP address from the list, the gateway will enable NAT and send such traffic to the VPN. The rest of the traffic will be routed to the default gateway without NAT.
For Linux systems, we can leave the default gateway and set IPSet and iproute2, and then configure them in the same way as the settings of the "intermediate" host router. In this case, at the client level, traffic will be selected using the same IPSet list. That is, what is in the list will be sent to the intermediate host router and then to the VPN. The rest will be routed by default.
Implementation
Let's assume that somewhere far away in the cloud, we already have a VPS server running Ubuntu or Debian. In other distributions, the differences will most likely only be in the installation of the necessary packages. This host will be used as a VPN server in our configuration. There are plenty of recommendations on which VPS is best to use on the Internet for different budgets, with different configurations and conditions.
Install OpenVPN, stunnel, and git on the server:
Code:
sudo apt install openvpn stunnel4 git
Next, we will use a ready-made script to configure the OpenVPN server. You can, of course, configure everything manually, and I advise you to do just that. Information on how to properly configure OpenVPN is easy to find on the Web. But if you need to get the result very quickly and you don't want to mess around, then here's a quick solution.
Code:
git clone https://github.com/Nyr/openvpn-install.git
cd openvpn-install
sudo ./openvpn-install.sh
We get the installation script and run it. It will help you create custom keys and certificates, and if necessary, change the network address. Everything is very accessible and clear. At the output, we will get one file for each user, inside which there will be a configuration key and certificates (server and user). Passing this file to the client.
Open the OpenVPN server configuration file and edit it. Select the appropriate port the one that will be available for connection on the server. It is better to use a more or less inconspicuous port (I chose 995, usually mail ports are left open), so that the client can be guaranteed to connect to the VPN server.
Here's what our config will look like:
![359f47503591c218eb726.jpg](https://telegra.ph/file/359f47503591c218eb726.jpg)
The next step is to set up stunnel:
Code:
sudo nano /etc/stunnel/stunnel.conf
![1743c4c1b1aaf6b4b4b3a.jpg](https://telegra.ph/file/1743c4c1b1aaf6b4b4b3a.jpg)
Everything is simple here:
- we describe where the logs will be saved;
- enter the name of the service in any form;
- choose whether the device is running in server or client mode. In this case, client = no indicates the server mode;
- accept = 443 specifies the port that we will connect to from the outside (port 443 was chosen for a reason - in 99% of cases it is always open, it is easier to pretend to be ordinary HTTPS, and we will not be noticed even at DPI).
Generating keys and certificates for stunnel:
Code:
sudo openssl req -nodes -new -days 365 -newkey rsa:1024 -x509 -keyout stunnelsrv.pem -out stunnel.pem
At this stage, it is important to remember that we have OpenVPN on port 995 proto tcp, dev tun0 and stunnel on port 443 running on the server side. All other settings are standard.
Going to the client:
Code:
sudo apt install iproute2 ipset stunnel4 git openvpn
Everything you need has been set up, and now we are configuring stunnel on the client side:
![6a73b99e889752a824696.jpg](https://telegra.ph/file/6a73b99e889752a824696.jpg)
Here we specify where to output logs, client mode is enabled. Using the accept Directive, we tell you which address and port to send the connection to and where the stunnel client should actually connect (the connect option). Well, which certificate to use.
Passing the OpenVPN client file from the server. We check the settings: port 995, proto tcp, dev tun0 is used. A very important point: we need to declare a route to our VPS through the default gateway. Otherwise, stunnel will establish a connection, then the VPN will connect and try to redirect everything to the tunnel, but stunnel will no longer be able to work, since the host and port will be unavailable. We also disable redirection of all traffic to the VPN, check the connection address and port. The address of the VPN server in the config will be 127.0.0.1 — that is, localhost. It is assumed that stunnel has already forwarded the required client port. You should get something like the following:
![0eb5a9671024141ac3cd1.jpg](https://telegra.ph/file/0eb5a9671024141ac3cd1.jpg)
So, OpenVPN and stunnel are installed and configured on the server and client. Secure connection is established. Next, we will consider each option in turn.
Option 1: VPN client on the user's machine
First of all, we will create a list of IP addresses that we will use next:
Code:
sudo ipset -N vpn iphash
Adding a single test address to it:
Code:
sudo ipset -A vpn 8.8.8.8
Now we need to label packets with destination addresses that match the list.
Code:
sudo iptables - OUTOUT -t mangle -m set --match-set vpn dst -j MARK --set-mark (1 или 0x1)
As a result of our actions, iptables will start marking such traffic if the destination address matches the address from The ipset list. Next, we will create a new routing table. to do this, we will write it in the /etc/iproute2/rt_tables file with a priority higher than default (253):
Code:
252 vpn
Now you need to create a rule and route for labeled packets.
Code:
sudo ip rule add table vpn prio 1000 fwmark (1 or 0x1)
sudo ip route add table vpn dev tun0 default
Don't forget to enable itrp_filter
to ensure asymmetric routing, we also allow packet forwarding between interfaces, in case someone needs to grant access to private resources on the local network.
Code:
sudo sysctl net.ipv4.tcp_fwmark_accept=1
sudo sysctl net.ipv4.conf.all.rp_filter=2
sudo net.ipv4.ip_forward=1
Now enable NAT for traffic that is routed to the VPN.
Code:
sudo iptables -t nat -I POSTROUTING -o tun0 -j MASQUERADE
If you need to provide access from the local network via your VPN, the iptables rule needs to be slightly tweaked, namely transferred to another chain.
Code:
sudo iptables -I PREROUTING -t mangle -m set --match-set tovpn dst -j MARK --set-mark 0x1
As a result, we get that all addresses from The ipset VPN list go through a secure connection, while the rest are routed through the default route.
Thank you all for your attention!