For a whole year (or two), I postponed publishing this article for a main reason β I had already published two articles where I described the process of creating a SOCKS router from a regular laptop running Debian.
However, since then, the stable version of Debian has been updated to Buster, and I received enough messages asking for help with the configuration, which means my previous articles are not exhaustive. Well, I suspected that the methods outlined in them do not fully cover all the intricacies of configuring Linux for routing in SOCKS. Moreover, they were written for Debian Stretch, and after upgrading to Buster, in the systemd initialization system, I noticed subtle changes in the interaction of services. Additionally, I did not use systemd-networkd in the articles, even though it is best suited for complex network configurations.
In addition to the aforementioned changes, my configuration has included services such as hostapd β a service for virtual access point creation, ntp for synchronizing time for local network clients, dnscrypt-proxy for encrypting connections via the DNS protocol and disabling ads on local network clients, and as I mentioned earlier, systemd-networkd for configuring network interfaces.
Hereβs a simple block diagram of the internal structure of such a router.

So, let me remind you what the goals of this series of articles are:
- To route all OS connections through SOCKS, as well as connections from all devices on the same network as the laptop.
- In my case, the laptop must remain fully mobile. That is, it should allow the use of a desktop environment and not be tied to a physical location.
- The last point implies connecting and routing solely through the built-in wireless interface.
- And, of course, to create a comprehensive guide, as well as to discuss the relevant technologies to the best of my modest knowledge.
What will be covered in this article:
- git β we will download the project repositories tun2socks, necessary for routing TCP traffic to SOCKS, and create_ap β a script for automating the configuration of a virtual access point using hostapd.
- tun2socks β we will build and install the systemd service.
- systemd-networkd β we will configure wireless and virtual interfaces, static routing tables, and packet forwarding.
- create_ap β we will set up the systemd service, configure it, and launch a virtual access point.
Optional steps:
- ntp β we will set up and configure a server for time synchronization on the clients of the virtual access point.
- dnscrypt-proxy β we will encrypt DNS requests, route them through SOCKS, and disable advertising domains for the local network.
Why all this?
This is one way to organize protection for TCP connections in a local network. The main advantage is that all connections go through SOCKS unless a static route is set through the original gateway. This means you don't need to configure the SOCKS server settings for individual programs or clients in the local network β they all go through SOCKS by default, as it is the default gateway until we specify otherwise.
Essentially, we add a second encrypting router as a laptop in front of the original router and use the original router's internet connection for the already encrypted SOCKS requests from the laptop, which, in turn, routes and encrypts the requests from the local network clients.
From the provider's perspective, we are constantly connected to a single server with encrypted traffic.
Accordingly, all devices connect to the virtual access point of the laptop.
Install tun2socks on the system
As long as your machine has internet access, download all necessary tools.
apt updateapt install git make cmakeDownload the badvpn package
git clone https://github.com/ambrop72/badvpn
A folder named badvpn will appear in your system.Create a separate folder for the build
mkdir badvpn-build
Go into it
cd badvpn-build
Build it tun2socks
cmake ../badvpn -DBUILD_NOTHING_BY_DEFAULT=1 -DBUILD_TUN2SOCKS=1
Install it on the system,
make install
- Parameter
-DBUILD_NOTHING_BY_DEFAULT=1disables building all components of the badvpn repository. - β
DBUILD_TUN2SOCKS=1enables building the component tun2socks. make installβ will install the tun2socks binary in your system at/usr/local/bin/badvpn-tun2socks.
Set up the tun2socks service in systemd
Create a file /etc/systemd/system/tun2socks.service with the following content:
[Unit]
Description=SOCKS TCP Relay
[Service]
ExecStart=/usr/local/bin/badvpn-tun2socks --tundev tun2socks --netif-ipaddr 172.16.1.1 --netif-netmask 255.255.255.0 --socks-server-addr 127.0.0.1:9050
[Install]
WantedBy=multi-user.target
--tundevβ takes the name of the virtual interface that we initialize using systemd-networkd.--netif-ipaddrβ the network address of the 'router' tun2socks to which the virtual interface connects. It is better to make it a separate .--socks-server-addrβ takes the socket (address:portof the SOCKS server).
If your SOCKS server requires authentication, you can specify the parameters. --username and --password.
Next, register the service
systemctl daemon-reloadAnd enable
systemctl enable tun2socksBefore starting the service, we'll provide it with a virtual network interface.
Let's switch to systemd-networkd
We enable systemd-networkd:
systemctl enable systemd-networkdDisable current network services.
systemctl disable networking NetworkManager NetworkManager-wait-online- NetworkManager-wait-online β this is a service that waits for a working network connection before systemd continues to start other services that depend on the network. We disable it as we will switch to the systemd-networkd equivalent.
Let's enable it right away:
systemctl enable systemd-networkd-wait-onlineConfigure the wireless network interface
Create a systemd-networkd configuration file for the wireless network interface /etc/systemd/network/25-wlp6s0.network.
[Match]
Name=wlp6s0
[Network]
Address=192.168.1.2/24
IPForward=yes
- Name β this is the name of your wireless interface. Identify it with the command
ip a. - IPForward β this directive enables packet forwarding on the network interface.
- Address is responsible for assigning an IP address to the wireless interface. We specify it statically because with the equivalent directive
DHCP=yes, systemd-networkd would create a default gateway in the system. Then all traffic would go through the original gateway instead of the future virtual interface in a different subnet. You can check the current default gateway with the commandip r
Create a static route for the remote SOCKS server
If your SOCKS server is not local, but remote, you need to create a static route for it. To do this, add a section Route at the end of the configuration file you created for the wireless interface with the following content:
[Route]
Gateway=192.168.1.1
Destination=0.0.0.0
Gatewayβ this is the default gateway or the address of your original access point.Destinationβ this is the address of your SOCKS server.
Configure wpa_supplicant for systemd-networkd
systemd-networkd uses wpa_supplicant to connect to a secure access point. When trying to 'bring up' the wireless interface, systemd-networkd starts the service wpa_supplicant@name, where name β this is the name of the wireless interface. If you haven't used systemd-networkd up to this point, this service is likely absent on your system.
Therefore, create it with the command:
systemctl enable wpa_supplicant@wlp6s0I used wlp6s0 as the name of your wireless interface. This name might be different for you. You can find it out with the command ip l.
Now the created service wpa_supplicant@wlp6s0 will start when the wireless interface is "brought up," but it will, in turn, look for the SSID settings and access point password in the file /etc/wpa_supplicant/wpa_supplicant-wlp6s0. Therefore, it is necessary to create it using the utility wpa_passphrase.
To do this, execute the command:
wpa_passphrase SSID password>/etc/wpa_supplicant/wpa_supplicant-wlp6s0.confwhere SSID β is the name of your access point, password β is the password, and wlp6s0 β is the name of your wireless interface.
Initialize the virtual interface for tun2socks
Create a file for initializing the new virtual interface in the system/etc/systemd/network/25-tun2socks.netdev
[NetDev]
Name=tun2socks
Kind=tun
- Name β is the name that systemd-networkd will assign to the future virtual interface upon initialization.
- Kind β is the type of the virtual interface. From the service name tun2socks, you can guess that it uses a type of interface
tun. - netdev β is an extension of the files that
systemd-networkdare used to initialize virtual network interfaces. The address and other network settings for these interfaces are specified in .network-files.
Create such a file /etc/systemd/network/25-tun2socks.network with the following content:
[Match]
Name=tun2socks
[Network]
Address=172.16.1.2/24
Gateway=172.16.1.1
Nameβ the name of the virtual interface that you specified in netdev-file.Addressβ the IP address that will be assigned to the virtual interface. It must be on the same network as the address you specified in the tun2socks serviceGatewayβ the IP address of the "router" tun2socks, which you specified when creating the systemd service.
Thus, the interface tun2socks has the address 172.16.1.2, while the service tun2socks β 172.16.1.1, meaning it acts as a gateway for all connections from the virtual interface.
Configure the virtual access point
Install dependencies:
apt install util-linux procps hostapd iw havegedDownload the repository create_ap to your machine:
git clone https://github.com/oblique/create_apChange to the repository folder on your machine:
cd create_apInstall it on the system:
make installYour system will have the config /etc/create_ap.conf. Here are the main options to edit:
GATEWAY=10.0.0.1β it is better to create a separate reserved subnet.NO_DNS=1β disable it, as this parameter will be managed by the systemd-networkd virtual interface.NO_DNSMASQ=1β disable it for the same reason.WIFI_IFACE=wlp6s0β the wireless interface of the laptop.INTERNET_IFACE=tun2socksβ the virtual interface created for tun2socks.SSID=hostapdβ the name of the virtual access point.PASSPHRASE=12345678β the password.
Don't forget to enable the service:
systemctl enable create_apEnable the DHCP server in systemd-networkd
The service create_ap initializes the virtual interface ap0The idea is that dnsmasq is 'hanging' on this interface, but why install unnecessary services when systemd-networkd has a built-in DHCP server?
To enable it, we will define the network settings for the virtual point. For this, create a file /etc/systemd/network/25-ap0.network with the following content:
[Match]
Name=ap0
[Network]
Address=10.0.0.1/24
DHCPServer=yes
[DHCPServer]
EmitDNS=yes
DNS=10.0.0.1
EmitNTP=yes
NTP=10.0.0.1
After the create_ap service initializes the virtual interface ap0, systemd-networkd will automatically assign it an IP address and enable the DHCP server.
The lines EmitDNS=yes and DNS=10.0.0.1 pass the DNS server settings to devices connected to the access point.
If you do not plan to use a local DNS server β in my case it's dnscrypt-proxy β you can set DNS=10.0.0.1 downward API support (simultaneously with this in DNS=192.168.1.1, where 192.168.1.1 β the address of your original gateway. Then the DNS queries from your host and local network will go unencrypted through your provider's servers.
EmitNTP=yes and NTP=192.168.1.1 pass the NTP settings.
The same goes for the line NTP=10.0.0.1.
Install and configure the NTP server
Install it on the system:
apt install ntp
Edit the config /etc/ntp.conf. Comment out the addresses of the standard pools:
#pool 0.debian.pool.ntp.org iburst
#pool 1.debian.pool.ntp.org iburst
#pool 2.debian.pool.ntp.org iburst
#pool 3.debian.pool.ntp.org iburst
Add the addresses of public servers, for example, Google Public NTP:
server time1.google.com iburst
server time2.google.com iburst
server time3.google.com iburst
server time4.google.com iburst
Provide access to the server for clients in your network:
restrict 10.0.0.0 mask 255.255.255.0
Enable broadcasting in your network:
broadcast 10.0.0.255
Finally, add the addresses of these servers to the static routing table. For this, open the wireless interface configuration file /etc/systemd/network/25-wlp6s0.network and add to the end of the section Route.
[Route]
Gateway=192.168.1.1
Destination=216.239.35.0
[Route]
Gateway=192.168.1.1
Destination=216.239.35.4
[Route]
Gateway=192.168.1.1
Destination=216.239.35.8
[Route]
Gateway=192.168.1.1
Destination=216.239.35.12You can find out the addresses of your NTP servers using the utility host as follows:
host time1.google.comInstall dnscrypt-proxy, remove ads and hide DNS traffic from your provider
apt install dnscrypt-proxyTo serve the DNS queries of the host and local network, edit the socket /lib/systemd/system/dnscrypt-proxy.socket. Change the following lines:
ListenStream=0.0.0.0:53
ListenDatagram=0.0.0.0:53Restart systemd:
systemctl daemon-reloadEdit the config /etc/dnscrypt-proxy/dnscrypt-proxy.toml:
server_names = ['adguard-dns']
To route connections through dnscrypt-proxy via tun2socks, add below:
force_tcp = true
Edit the config /etc/resolv.conf, which informs the DNS server about the host.
nameserver 127.0.0.1
nameserver 192.168.1.1The first line enables the use of dnscrypt-proxy, while the second uses the original gateway, in case the dnscrypt-proxy server is unavailable.
Done!
Reboot or stop the active network services:
systemctl stop networking NetworkManager NetworkManager-wait-onlineAnd restart all necessary ones:
systemctl restart systemd-networkd tun2socks create_ap dnscrypt-proxy ntpAfter rebooting or restarting, you will have a second access point that routes the host and local network devices to SOCKS.
This is what the output looks like ip a of a regular laptop:
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: tun2socks: mtu 1500 qdisc pfifo_fast state UP group default qlen 500
link/none
inet 172.16.1.2/24 brd 172.16.1.255 scope global tun2socks
valid_lft forever preferred_lft forever
inet6 fe80::122b:260:6590:1b0e/64 scope link stable-privacy
valid_lft forever preferred_lft forever
3: enp4s0: mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000
link/ether e8:11:32:0e:01:50 brd ff:ff:ff:ff:ff:ff
4: wlp6s0: mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 4c:ed:de:cb:cf:85 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.2/24 brd 192.168.1.255 scope global wlp6s0
valid_lft forever preferred_lft forever
inet6 fe80::4eed:deff:fecb:cf85/64 scope link
valid_lft forever preferred_lft forever
5: ap0: mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 4c:ed:de:cb:cf:86 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.1/24 brd 10.0.0.255 scope global ap0
valid_lft forever preferred_lft forever
inet6 fe80::4eed:deff:fecb:cf86/64 scope link
valid_lft forever preferred_lft forever
As a result,
- The provider only sees the encrypted connection to your SOCKS server, meaning they cannot see anything.
- However, they can see your NTP requests. To prevent this, remove static routes for the NTP servers. However, it is not guaranteed that your SOCKS server allows the NTP protocol.
A workaround noted on Debian 10
If you try to restart the network service from the console, it will crash with an error. This is because its part in the form of a virtual interface is bound to the tun2socks service, meaning it is in use. To restart the network service, you first need to stop the tun2socks service. But, I think, if you read this far, this is definitely not a problem for you!
Links
Source: habr.com
