Compare commits

...

9 Commits
v0.1.0 ... main

8 changed files with 186 additions and 69 deletions

View File

@ -1,22 +0,0 @@
pkgbase = nnss
pkgdesc = Network Namespace setup using SSH SOCKS proxy
pkgver = 0.1.0
pkgrel = 2
url = https://gitea.balki.me/balki/nnss
arch = any
license = MIT
depends = tun2socks
source = nnss-ssh@.service
source = nnss-tunsocks@.service
source = ssh_config
source = tunsocks.sh
source = README.md
source = tmpfiles.conf
sha256sums = 59abec374b4430510f40fa2184863c5978f638047f5740ed2bf86a5ec6f92dff
sha256sums = af660f552d439bc9134a0d0774fed3a765448abfebee39a586c05df56e9ff32d
sha256sums = cb57dd0be323adc05d70d6b28ed7d79261c5c7215586e604138a164ae88aeeca
sha256sums = f35c22bb12d020428787828107ee379dd147e485edfdac687fed92d73d81d418
sha256sums = 20272994a3f3235ae79b24c4ab7c78a21aeadfd5ca03df98a6b099aac6a623a4
sha256sums = 654a3615be4eb635957a4ab33e733a1c6655225f6ff34ec8a58f6dabc9ac0d70
pkgname = nnss

3
.gitignore vendored
View File

@ -1,3 +0,0 @@
nnss*pkg.tar.zst
src/
pkg/

20
Makefile Normal file
View File

@ -0,0 +1,20 @@
PREFIX=/usr
install:
install -Dm 644 nnss-ssh@.service -t "$(PREFIX)/lib/systemd/system"
install -Dm 644 nnssA@.service -t "$(PREFIX)/lib/systemd/system"
install -Dm 644 nnssB@.service -t "$(PREFIX)/lib/systemd/system"
install -Dm 644 ssh_config -t "$(PREFIX)/lib/nnss"
install -Dm 755 tunsocks.sh -t "$(PREFIX)/lib/nnss"
install -Dm 644 README.md -t "$(PREFIX)/share/doc/nnss"
install -Dm 644 LICENSE -t "$(PREFIX)/share/doc/nnss"
install -Dm 644 tmpfiles.conf "$(PREFIX)/lib/tmpfiles.d/nnss.conf"
uninstall:
rm -rf "$(PREFIX)/lib/nnss" \
"$(PREFIX)/share/doc/nnss" \
"$(PREFIX)/lib/tmpfiles.d/nnss.conf" \
"$(PREFIX)/lib/systemd/system/nnssA@.service" \
"$(PREFIX)/lib/systemd/system/nnssB@.service" \
"$(PREFIX)/lib/systemd/system/nnss-ssh@.service"

113
README.md
View File

@ -1,20 +1,43 @@
# Network Namespace setup using SSH SOCKS proxy
Create network namespace where all¹ network requests go via ssh connection.
Create network namespace where all¹ network requests go via socks proxy.
## Creating new namespace
## Dependency
1. Create a simple ssh config at `/etc/nnss/<namespace_name>/config`. This will be
included with [other settings][0].
2. Create the ssh private key at `/etc/nnss/<namespace_name>/privatekey`
3. [Edit][1] your service file to include below properties
Depends on [tun2socks][4]. Install from [AUR][5] or compile from [source][6].
## Installing
1. Install from [AUR][2].
2. Manual installation:
This will install under `/usr`
```sh
sudo make install
```
Change install directory using `PREFIX`
```sh
sudo make PREFIX=/usr/local install
```
For uninstall, run `make uninstall` or `make PREFIX=<prefix> uninstall`
## Type A: Use ssh to create socks proxy
1. Create a simple ssh config at `/etc/nnss/<namespace_name>/config`. This will
be included with [other settings][0].
2. Copy your ssh private key to `/etc/nnss/<namespace_name>/privatekey`
3. [Edit][1] your application's service file to include below properties
```systemd
[Unit]
Requires=nnss-tunsocks@<namespace_name>.service
After=nnss-tunsocks@<namespace_name>.service
Requires=nnssA@<namespace_name>.service
After=nnssA@<namespace_name>.service
[Service]
NetworkNamespacePath=/run/netns/<namespace_name>
NetworkNamespacePath=/run/netns/<namespace_name>ns
```
### Example
@ -31,10 +54,15 @@ Port 8822 # If the ssh server is not on default port 22
```
## Testing namespace
### Testing namespace
```bash
sudo systemd-run --property=NetworkNamespacePath=/run/netns/vps1ns --property=User=$USER --property=Requires=nnss-tunsocks@vps1.service --property=After=nnss-tunsocks@vps1.service --shell
sudo systemd-run \
--property=NetworkNamespacePath=/run/netns/vps1ns \
--property=User=$USER \
--property=Requires=nnssA@vps1.service \
--property=After=nnssA@vps1.service \
--shell
[sudo] password for balki:
Running as unit: run-p233279-i233579.service
Press ^] three times within 1s to disconnect TTY.
@ -55,20 +83,65 @@ xx.xx.xx.xx
valid_lft forever preferred_lft forever
inet6 fe80::fd64:c3f3:ce6:650c/64 scope link stable-privacy proto kernel_ll
valid_lft forever preferred_lft forever
Finished with result: success
Main processes terminated with: code=exited, status=0/SUCCESS
Service runtime: 1min 4.383s
CPU time consumed: 201ms
Memory peak: 5.7M (swap: 0B)
IP traffic received: 3.2K sent: 1.3K
IO bytes written: 304K
```
## Type B: Use existing socks proxy
1. Create an environment file at `/etc/nnss/env_<namespace_name>`. This file
should contain one environment variable `SOCKS_PROXY`. See example below
2. [Edit][1] your application's service file to include below properties
```systemd
[Unit]
Requires=nnssB@<namespace_name>.service
After=nnssB@<namespace_name>.service
[Service]
NetworkNamespacePath=/run/netns/<namespace_name>ns
```
### Example
Assuming tor daemon is running configured to listen on socks proxy on port 9050.
```bash
sudo tee /etc/nnss/env_tor > /dev/null
SOCKS_PROXY=socks5://127.0.0.1:9050
```
Create a shell inside tor namespace
```bash
sudo systemd-run \
--property=NetworkNamespacePath=/run/netns/torns \
--property=User=$USER \
--property=Requires=nnssB@tor.service \
--property=After=nnssB@tor.service \
--shell
```
Quick check:
```bash
curl --silent https://check.torproject.org | grep -E "Sorry|Congratulations"
Congratulations. This browser is configured to use Tor.
```
### Comparison with torsocks
[torsocks][7] can be used to run a program to connect via tor. This works by
replacing network function calls in libc using `LD_PRELOAD`.
This does not work with programs not using libc functions for networking. E.g.
go programs. Or when a sub-process is created wihtout passing down
`LD_PRELOAD`. Network namespaces are more secure and works for any program.
## ¹DNS
DNS by default still goes via host.
[0]: ./ssh_config
[1]: https://wiki.archlinux.org/title/Systemd#Editing_provided_units
[2]: https://aur.archlinux.org/packages/nnss
[4]: https://github.com/xjasonlyu/tun2socks
[5]: https://aur.archlinux.org/packages/tun2socks-git
[6]: https://github.com/xjasonlyu/tun2socks/wiki/Install-from-Source
[7]: https://gitlab.torproject.org/tpo/core/torsocks

View File

@ -1,6 +1,7 @@
[Unit]
Description=Create SSH connection to %I
After=network.target
Requires=network-online.target
After=network-online.target
StopWhenUnneeded=yes
[Service]

View File

@ -9,7 +9,7 @@ StopWhenUnneeded=yes
Type=notify
NotifyAccess=all
RuntimeDirectory=nnss-tunsocks%i
RuntimeDirectory=nnssA%i
ExecStart=/usr/lib/nnss/tunsocks.sh "%i" setup
ExecStop=/usr/lib/nnss/tunsocks.sh "%i" cleanup

17
nnssB@.service Normal file
View File

@ -0,0 +1,17 @@
[Unit]
Description=Create network namespace and tun device to %I
StopWhenUnneeded=yes
[Service]
Type=notify
NotifyAccess=all
RuntimeDirectory=nnssB%i
# Add SOCKS_PROXY environment variable to below file. E.g.
# SOCKS_PROXY=socks5://127.0.0.1:9050
EnvironmentFile=/etc/nnss/env_%i
ExecStart=/usr/lib/nnss/tunsocks.sh "%i" use_env setup
ExecStop=/usr/lib/nnss/tunsocks.sh "%i" use_env cleanup

View File

@ -2,38 +2,69 @@
set -xeuo pipefail
pidfile=${RUNTIME_DIRECTORY:-/tmp}/tunsocks.pid
rtdir=${RUNTIME_DIRECTORY:-/tmp}
pidfile="$rtdir/tunsocks.pid"
nsname="$1"
device="tun${nsname}"
ns="${nsname}ns"
socketpath="/run/nnss-${nsname}/sock"
setup()
{
ip tuntap add mode tun dev "$device"
if [ "$2" = use_env ]; then
proxy="$SOCKS_PROXY"
shift
else
proxy="socks5:///run/nnss-${nsname}/sock"
fi
/usr/bin/tun2socks -device "$device" -proxy "socks5://$socketpath" &
echo "$!" > "$pidfile"
sleep 5
setup() {
ip tuntap add mode tun dev "$device"
ip netns add "$ns"
ip link set "$device" netns "$ns"
chan="$rtdir/chan"
mkfifo "$chan"
ip -n "$ns" addr add 198.19.1.1/30 dev "$device"
ip -n "$ns" link set dev "$device" up
ip -n "$ns" route add default via 198.19.1.1 dev "$device" metric 100
ip -n "$ns" link set lo up
systemd-notify --ready
wait
{
sleep 10
echo TIMEOUT >"$chan"
} &
timeout_pid=$!
done_cmd="sh -c 'echo DONE > \"$chan\"'"
tun2socks -device "$device" -proxy "$proxy" -tun-post-up "$done_cmd" &
echo "$!" >"$pidfile"
read -r status <"$chan"
if [ "$status" = DONE ]; then
kill "$timeout_pid"
else
echo "Failed: $status"
return 1
fi
ip netns add "$ns"
ip link set "$device" netns "$ns"
ip -n "$ns" addr add 198.19.1.1/30 dev "$device"
ip -n "$ns" link set dev "$device" up
ip -n "$ns" route add default via 198.19.1.1 dev "$device" metric 100
ip -n "$ns" link set lo up
systemd-notify --ready
wait
}
cleanup()
{
ip tuntap del mode tun dev "$device" || true
kill "$(cat "$pidfile")"
ip -n "$ns" tuntap del mode tun dev "$device"
ip netns del "$ns"
cleanup() {
# Cleanup as much as possible. Don't stop on first error
set +e
# If the script failed after creating the device before moving it to namespace
ip tuntap del mode tun dev "$device"
# Regular cleanup when when shutdown normally
kill "$(cat "$pidfile")"
ip -n "$ns" tuntap del mode tun dev "$device"
ip netns del "$ns"
}
$2