Abstract: Isolating applications at the network level using Linux network namespaces. The organization of SSH-tunnels.
Traditionally, most of the article will be devoted to the theory, and boring scripts - at the end of the article. Steam will be used as a subject for experiments, although the writing applies to any application, including web browsers.
Instead of entry. I'll just show this picture:

147% ... It reminds me of something. However, habr is not for politics.
')
The price of games in Steam depends on the region. Region - from IP'shnika. There is a desire to have prices in rubles, and not in euros.
To do this, we use VPN over SSH using tun-devices, plus network namespaces to isolate the application from all other network devices.
Network namespaces
Traditionally, an application that runs even with user rights has full access to the network. It can use any network address that exists in the system to send packets.
Moreover, most desktop applications do not understand anything at all in interfaces, since they assume that the system has only one network interface and does not allow to specify which of the interfaces should be used. Server software usually has this option (what address to use as the sender's address), but for desktops it is an unaffordable luxury.
If we have several interfaces (one of which relates to a VPN), then there are no regular methods to say incentive to use it, and not eth0 / wlan0. More precisely, we can "wrap" all traffic in a VPN, but this is not always desirable. At a minimum, latency growth and a decrease in speed (even if VPN leads to a super fast server, an increase in latency, an overhead from the tunnel, and a fixed width of the local channel set TCP into a position where you have to cut the speed). As a maximum, it’s one thing to “buy through Russian VPN”, and another thing is to let all traffic go there. I am not at all tempted by the use of a VPN
to get Roskomnadzor protection against opposition and free-thinking .
Under these conditions, there is a great desire to leave one to one specific application and a given network interface. One. Configured for the needs of this application only.
To solve this problem in Linux, for a long time (already since 2007) there exists a technology called network namespaces, that is, namespace for networks. The essence of the technology: the similarity of “directories” is created above network interfaces, in each directory there can be several network interfaces and applications. An application that finds itself in a given network namespace can use (and sees) only those network interfaces that are assigned to this space.
The picture below explains what is happening:

Such an abundance of configurations, of course, not quite the desktop, but it will allow to explain what is happening in its pure form.
Different namespaces are highlighted in different colors. These interfaces are available only from the specified namespaces and nothing else. For example, the red namespace has access only to tap1, veth1 and lo, blue to eth1, eth2, lo and veth0, green to tun0 and lo. Beyond the namespaces, there are eth0, the own interface br1, tap0 and lo.
Note that each namespace has its own lo! If you listen to mysql in blue namespace for lo, then you will not be able to access it from green (and anyone other than blue) namespace. Perhaps this is the most pleasant feature. The second feature is that we can use the same IP address in different namespaces on different interfaces, and there will be nothing for us. Of course, the routing table for each namespace is different.
The attentive reader sensed the spirit of virtualization. Of course, yes. Network namespaces (along with other technologies at this level) are an important part of LXC (container virtualization in Linux). But, unlike openvz and many other similar technologies, the LXC components are so common that they can be used as stand-alone tools. And this is the correct unix-way: everyone does only one thing, but well; although purists may say that "shoving everything into the core is bad."
The most interesting picture is obtained if you leave the application with the tun / tap interface, which leads beyond the current network (in the picture above - the green namespace with a single tun). If tun lands somewhere outside the computer (for example, on a vpn server), then the application will have no way to understand what network settings are really on the computer. If a VPN, for example, leads from Cyprus to Russia, then any application running in the green namespace will receive the address from Russia and go online as if it were in Russia. Actually, this is what we need in order for Steam to believe that we have Russian IP and agreed to sell the game for half the price.
With the definition of the country at Steam everything is somewhat strange. Without VPN, Steam sometimes shows me prices in euros, sometimes in rubles, and I could not understand the patterns. Russian VPN removed all questions - prices are always in rubles .
A brief tip on working with network namespaces (practical tips near the end of the article):
ip netns
- list of network namespaces (in all ip netns commands, you can abbreviate to ip net)
ip netns add/delete foo
- create / delete network namespace with the name foo
ip netns exec foo /usr/bin/bin
- run the program in the specified network namespace (note that you cannot drag applications that are already running)
ip link set eth99 netns foo
- shove an interface into a given space
And a few tricks:
ip netns exec foo ip link
- list of interfaces inside the foo space
ip netns exec foo tcpdump -ni eth99
- tcpdump on it. Attention, due to the specific work of the exec, the output to the screen will appear only after pressing Ctrl-C. If annoying - see below.
sudo ip netns exec foo login -f username
- run login inside namespace'a. The logged-in user will already work in the specified namespace with well-configured settings for the terminal / group leader, etc.
VPN organization via SSH
I do not like openvpn, openswan and other applications for redundancy. I recognize their need in some situations, but when I can, I try to use SSH. There are several reasons:
1) SSH is out of the box on any server.
2) SSH uses TCP, not gre / udp, and if you need to connect from an exotic place with a fucking WiFi, then ssh on ports 22 and 443 is our everything. If port 22 can still be closed, then 443 is definitely not; it is used by HTTPS (and in case of blocking, indignant hamsters will carry everything on their way to google / facebook, etc.)
3) SSH-client is on any machine within reach, that is, I can pick up the tunnel I need from any unix-machine. In 3-5 steps - with windows.
4) Tuning degree settings are easy to adjust. If I only need socks-proxy, then I will not invent l2-tunnels.
5) Without additional shamanism, you can have several parallel connections, and in any combination - to one server from different clients, to different servers from one client, etc. Absolutely
fucked heads can generally connect continents and networks to a single L2-segment by means of a lonely little bug sitting on 3g somewhere in the fifth point of the world behind hardcore nato with closed ports. And it will even work (to the extent that 3g in the fifth point of the world will be able to digest the broadcasts / multicastes that fly through L3).
Although the main reason is even simpler: SSH is a regular toolkit, and it can do everything it needs. Why something else?
So the SSH tunnel theory
TUN interfaces
The TUN interface is very simple: it creates a virtual network interface (tun0, tun1, etc.) in the system, which with its other “end” looks at the fd (file descriptor) of the program that created it. The program decides what to do with traffic from fd. And the applications in the system decide for themselves what to do with the network interface.
In the case of SSH, we tell the SSH client to create a tun-interface for our part, an SSH server for our part, and connect them. It turns out that traffic on the one hand (from the client) came in, on the other hand (from the server) came out. And vice versa. What is not a tunnel? What is not vpn? Taking into account that SSH can also encrypt traffic, we get a ready VPN. Inside SSH, this is called a channel, and it multiplexes them, but we don’t really care about it.
Here is a simple drawing of what is happening:

Note that we need cooperation from the SSH server. We will discuss the permission to create tunnels on the server in the section below. There will also be details on how to configure NAT, addressing and other things so that the Freedom arrow works.
A note in the margin: in addition to the tun-interfaces, there are also tap-interfaces. They allow you to combine L2-segments. This is hell, horror, sodomy and intoxication, but if someone really wants to, then he can try to combine a couple of networks from different data centers via an SSH connection to a homely-made machine. It will even work (I can’t vouch for the consequences).
Practical action
Training:- Copy the SSH key to root to the server (if there is no key, generate:
sudo ssh-keygen
). I usually make the key to the local root so as not to confuse it with my key. The key is copied using the sudo ssh-copy-id root@server
command. - Check that SSH on the remote server is allowed to use tunnels. In the
/etc/ssh/sshd_config
PermitTunnel
variable must be uncommented and set to yes
. - Choose an arbitrary number (echo $ RANDOM). This will be our tunnel number. Remember it (or take another favorite number, for example, 42).
- Set up a remote server. I am writing for debian / ubuntu, a process for other distributions / OS - see the documentation for setting up the network for them. In the / etc / networking / interfaces file we create the following lines:
allow-hotplug tun42 auto tun42 iface tun42 inet static address 100.64.42.1 netmask 255.255.255.0 pre-up iptables -A POSTROUTING -t nat -s 100.64.42.0/24 -j MASQUERADE post-down iptables -D POSTROUTING -t nat -s 100.64.42.0/24 -j MASQUERADE
This will allow us to automatically receive the configured interface every time the tun42 interface appears on the server. At the same time, we enable NAT to translate our packets from the tunnel, and turn it off as soon as the interface disappears. - Enable server routing.
/etc/sysctl.d/enable_routing.conf
net.ipv4.conf.all.forwarding = 1
We are almost done. It remains only to run steam. Everything written on the local machine.
- Shut down all previous copies of steam, including the tray icon
- Connect to server:
sudo ssh -w 42:42 root@server
. The -w option says to create tun42 locally and link it (having created) with the remote tun42. - In the next console:
xhost + sudo ip net add steam sudo ip link set netns steam dev tun42 sudo ip net exec steam ip addr add 100.64.42.2/24 dev tun42 sudo ip net exec steam ip link set up dev tun42 sudo ip net exec steam ip route add default via 100.64.42.1 sudo ip net exec steam login -f $USER export DISPLAY=:0 steam
xhost +
allows xhost +
to connect to your X server (be careful). Paranoids can learn man xhost for more precise rules.
ip net add
and ip net exec
are shortcuts from ip netns add
and ip netns exec
- create a network namespace, and start a new user session from which we work. export DISPLAY=:0
says “use first X server. By default, this variable is reset at login, and without it, steam will not be able to connect to the X-server
Own, everything. At the exit, we have Russian prices in Steam and Russian censorship. Fortunately, it will only be protected by steam, and the browser in the next window will use the not very fast, but very free Cyprus Internet.
In the following parts:
- How to run a 32-bit steam on x86_64 machine
- How to isolate steam completely, so that it works, but it has never been run from the root or the main user. Love and hate with pulsadwio, dri, methods for determining missing libraries, debugging Steam itself