Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
W
web
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Murukesh Mohanan
web
Commits
1a62fa0e
Commit
1a62fa0e
authored
Dec 03, 2020
by
Murukesh Mohanan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
blog post on network namespaces
parent
54407b4b
Pipeline
#1379
failed with stage
Changes
1
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
112 additions
and
0 deletions
+112
-0
_posts/2020-12-03-poking-pi-ii.md
_posts/2020-12-03-poking-pi-ii.md
+112
-0
No files found.
_posts/2020-12-03-poking-pi-ii.md
0 → 100644
View file @
1a62fa0e
---
layout
:
post
title
:
'
Poking
around
a
Pi,
Part
II:
VPNs
and
Network
Namespaces'
tags
:
[
tech
,
linux
]
description
:
Using a VPN only for a select group of applications
---
A few weeks ago, I had occasion to find out how Docker overlay networks could be created manually, which led me to learn
more about network namespaces in Linux. I already knew the concepts behind various namespaces (user, PID, mount, etc.),
but this was the first time in a long time that I had occasion to set one up myself. In the process, I came up on one
solution to a problem that I'd been having recently: applying a VPN only to some applications.
<aside>
I know I promised to talk about Nextcloud in my last post over a year ago. However, in the months since, I had to
wipe and reinstall the Pi, and I ended up choosing not to install Nextcloud this time around. Instead, I connected it to
my TV, and installed Kodi. That has turned out to be far more useful for my purposes than Nextcloud ever was.
</aside>
<!-- section -->
Some time ago, I bought a subscription for Tunnelbear, and they support
[
Linux via OpenVPN
][
tb-linux
]
. I started using
it on my Pi, but to my dismay, I found that the VPN routing prevented incoming connections from the internet from being
properly handled. This caused a couple of problems:
1.
This broke SSH from outside.
2.
I could no longer run an externally-accessible web server from the Pi. As a side-effect, Let's Encrypt certificate
renewal via certbot could no longer be automated, since it would only work when the VPN was off.
The first could have been something of a deal-breaker, but since I accessed the Pi via SSH from the internet only
rarely, I was willing to let the VPN run as-is for the time being. I investigated online, and most solutions seemed to
recommend setting up another routing table and using
`iptables`
to mark the traffic (via, e.g., matching the user) to
use the new routing table. I didn't find this particularly appealing - I didn't want to go about running some process
under a different group or user, and I didn't want to mess with whatever routing OpenVPN deemed appropriate. Different
strokes and all...
<!-- section -->
Enter network namespaces aka netns. The idea itself is old (see, for example, [this 7-year-old
post](http://www.evolware.org/?p=293)); I just happened to stumble upon it recently. In short, the key element driving
the netns solution is the Virtual Ethernet Device aka [
`veth`
]. These are pairs of linked devices, where:
> Packets transmitted on one device in the pair are immediately received on the other device.
By keeping each interface of a veth pair in different namespaces, we can have easy communication between the two. So,
we'll have the default namespace, which is where we normally operate, and we will have a new namespace where the VPN
(and any applications that need the VPN) will operate.
The arcane incantations required are:
```
NS_NAME=vpn
ip netns add "$NS_NAME"
ip netns exec "$SHELL"
ln -s /proc/1/ns/net /var/run/netns/default
ip link add dev veth1 mtu 1500 type veth peer name veth2 mtu 1500
ip link set dev veth2 netns default
ip addr add dev veth1 10.0.0.1/24
ip link set veth1 up
ip netns exec default ip link set veth2 up
ip route add 192.168.0.7/32 dev veth1
ip route add default via 192.168.0.7
ip netns exec default ip route add 10.0.0.0/24 dev veth2
ip netns exec default iptables -A FORWARD -i veth2 -o eth0 -j ACCEPT
ip netns exec default iptables -A FORWARD -o veth2 -i eth0 -j ACCEPT
ip netns exec default iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
```
What do these commands do? Let's examine them block by block.
1.
Set up the namespace and enter it:
```
NS_NAME=vpn
ip netns add "$NS_NAME"
ip netns exec "$SHELL"
ln -s /proc/1/ns/net /var/run/netns/default
```
Here, we create a new network namespace named "`vpn`", and start a shell in it. Since the default namespace probably
doesn't have a name, we set a name for it (oddly enough, `default`).
2.
Create the veth pair and move one to the default namespace (we're already in a shell in the new namespace, remember):
```
ip link add dev veth1 mtu 1500 type veth peer name veth2 mtu 1500
ip link set dev veth2 netns default
```
3.
Bring up our veth interfaces and assign them IPs:
```
ip addr add dev veth1 10.0.0.1/24
ip link set veth1 up
ip netns exec default ip link set veth2 up
```
4.
Route to the external network via your proper network interface (here, I'm assuming it's IP is 192.168.1.2.)
```
ip route add 192.168.1.2/32 dev veth1
ip route add default via 192.168.1.2
```
5.
Set up packet forwarding using iptables:
```
ip netns exec default ip route add 10.0.0.0/24 dev veth2
ip netns exec default iptables -A FORWARD -i veth2 -o eth0 -j ACCEPT
ip netns exec default iptables -A FORWARD -o veth2 -i eth0 -j ACCEPT
ip netns exec default iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
```
Then run OpenVPN in this network namespace (for example, by running the
`openvpn`
command itself here, or by using
systemd to link it to this namespace).
[
tb-linux
]:
https://www.tunnelbear.com/blog/linux_support/
[
`veth`
]:
https://man7.org/linux/man-pages/man4/veth.4.html
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment