Browse Source

added everything

master
delbonis 1 year ago
commit
20cb3f17b9
9 changed files with 326 additions and 0 deletions
  1. 42
    0
      README.md
  2. 11
    0
      config.txt
  3. 119
    0
      natfwd.sh
  4. 45
    0
      transmissionwrap.sh
  5. 43
    0
      vpnhook.sh
  6. 14
    0
      vpnns-ns.service
  7. 16
    0
      vpnns-transmission.service
  8. 12
    0
      vpnns-vpn.service
  9. 24
    0
      vpnwrap.sh

+ 42
- 0
README.md View File

@@ -0,0 +1,42 @@
# vpnwrap

scripts for doing things

it runs a thing in a separate net namespace with only a vpn's network interface
so it's literally impossible for it to access the outside world, but it also
opens a single port into the program from your local machine so that you can
still talk to it for like rpcs or whatever

you'll probably have to modify these for your own setup, but I put everything
in vars at the top of scripts so it's not too hard, just search for `CONFIG:`
and then comment out the `exit 1` if there is one

* mostly in config.txt
* some things in transmissionwrap.sh
* take a look at natfwd.sh in case you need to change anything there

## dependencies

* iptables
* ufw
* transmission
* openvpn
* bash I guess

## installation

I set most this up on `/opt/vpnwrap` so the systemd services are written
assuming that, but once you create the dirs for everything it's fairly easy

make sure you download config files for your vpn, and configure it for those

the only other thing to remember is to deal with the dns resolver config, since
in a net namespace glibc doesn't use `/etc/resolv.conf`

add this to `/etc/netns/vpnns/resolv.conf` (or whatever) to fix that

```
nameserver 208.67.222.222
nameserver 208.67.220.220
```


+ 11
- 0
config.txt View File

@@ -0,0 +1,11 @@
# CONFIG: comment out the exit line after you configure these
exit 1
EXTPORTS='put your ports here, not commas just spaces'
EXTIF=put your network local ip addr here, the 192.168.0.0 one
NSNAME=vpnns

# don't forget to download/configure these too
VPNCONFIG=$SCRIPTPATH/mullvad_config_linux_nl_ams/mullvad_nl_ams.conf
VPNCA=$SCRIPTPATH/mullvad_config_linux_nl_ams/mullvad_ca.crt
VPNCREDS=$SCRIPTPATH/mullvad_config_linux_nl_ams/mullvad_userpass.txt


+ 119
- 0
natfwd.sh View File

@@ -0,0 +1,119 @@
#!/bin/bash

if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ]; then
echo 'usage: ./natfwd.sh <action> <extif> <port> <netns>'
exit 1
fi

if [ "$UID" -ne 0 ] && [ -z "$SKIP_ROOT_CHECK" ]; then
echo 'must be root!'
exit 1
fi

# Check if we should add an exemption for UFW.
ufw=no
if [ "$1" = "--ufw" ]; then
ufw=yes
shift
fi

action=$1
extip=$2
ports=$3
netnsname=$4

pipeouter=$netnsname"_veth0"
pipeinner=$netnsname"_veth1"

# use /31 here to minimize chance of something fucking up later
# CONFIG: change pouterip and pinnerip to something in case there's a conflict,
# but there probably won't be
pouterip=192.168.69.42
pinnerip=192.168.69.43
pouteripmasked=$pouterip/31
pinneripmasked=$pinnerip/31

# Used in testing:
# -A PREROUTING -d 192.168.1.9/32 -p tcp -m tcp --dport 1337 -j DNAT --to-destination 10.13.37.69
# -A POSTROUTING -d 10.13.37.69/32 -p tcp -m tcp --dport 1337 -j SNAT --to-source 10.13.37.42
dnatrule="PREROUTING -d $extip -p tcp --dport $port -j DNAT --to-destination $pinnerip"
snatrule="POSTROUTING -d $pinnerip -p tcp --dport $port -j SNAT --to-source $pouterip"

function get_dnat_rule {
port=$1
echo "PREROUTING -d $extip -p tcp --dport $port -j DNAT --to-destination $pinnerip"
}

function get_snat_rule {
port=$1
echo "POSTROUTING -d $pinnerip -p tcp --dport $port -j SNAT --to-source $pouterip"
}

function get_ufw_rule {
port=$1
echo "proto tcp from any to $pinnerip port $port"
}

# CONFIG: make sure this is set right
ufwcomment="natfwd_"$netnsname

if [ $action = "enable" ]; then
echo 'enabling'
set -x

# Make sure we have IP forwarding enabled. We don't bother disabling
# this later.
sysctl -w net.ipv4.ip_forward=1 > /dev/null

# Create the interface and move to the network namespace.
ip link add $pipeouter type veth peer name $pipeinner
ip link set $pipeinner netns $netnsname

# Assign IP addresses to the new devices.
ip addr add $pouteripmasked dev $pipeouter
ip netns exec $netnsname ip addr add $pinneripmasked dev $pipeinner

# Create the routing rules to allow the packets.
for p in $ports; do
iptables -t nat -A $(get_dnat_rule $p)
iptables -t nat -A $(get_snat_rule $p)
done

[ "$ufw" = "yes" ] && [ -z "$(ufw status | grep '# $ufwcomment')" ] && \
for p in $ports; do
ufw route allow $(get_ufw_rule $p) comment $ufwcomment
done

# Enable the interfaces.
ip link set dev $pipeouter up
ip netns exec $netnsname ip link set dev $pipeinner up

elif [ $action = "disable" ]; then
echo 'disabling'
set -x

# Delete the routing rules. Deleting the interfaces doesn't
# automatically remove these.
for p in $ports; do
iptables -t nat -D $(get_dnat_rule $p)
iptables -t nat -D $(get_snat_rule $p)
done
if [ "$ufw" = "yes" ]; then
rulenum=$(ufw status numbered | grep "# $ufwcomment" | awk '{ print substr($1, 2, length($1) - 2) }')
if [ -n "$rulenum" ]; then
yes | ufw delete $rulenum
fi
fi

# Deleting this interface deletes everything else associated with it.
ip link delete $pipeouter

else
echo 'actions are "enable" or "disable"'
exit 1
fi

set +x
echo 'OK'


+ 45
- 0
transmissionwrap.sh View File

@@ -0,0 +1,45 @@
#!/bin/bash

SCRIPTPATH=$(dirname $0)
source $SCRIPTPATH/config.txt

# CONFIG: comment this line out when you set the daemondir to what you want
exit 1
DAEMONDIR=/var/lib/transmission/info

PIDFILE=$DAEMONDIR/transmission.pid

function natfwd_do {
$SCRIPTPATH/natfwd.sh --ufw $1 $EXTIF "$EXTPORTS" $NSNAME
}

case $1 in
enable)
set -e

natfwd_do enable

echo 'VPN IP address:' $(ip netns exec $NSNAME curl ifconfig.me)

ip netns exec $NSNAME \
/usr/bin/transmission-daemon --log-error -g $DAEMONDIR -x $PIDFILE

;;

disable)
set -x

if [ -f "$PIDFILE" ]; then
xmpid=$(cat $PIDFILE | sed 's/\;.*//')
echo 'killing' $xmpid
kill -15 $xmpid
fi

natfwd_do disable

;;
reload)
/bin/kill -s HUP $(cat $PIDFILE)
;;
esac


+ 43
- 0
vpnhook.sh View File

@@ -0,0 +1,43 @@
#!/bin/bash

SCRIPTPATH=$(dirname $0)
source $SCRIPTPATH/config.txt

#echo "===== $script_type =====" >> hook.txt

case $script_type in
up)
# Make the namespace and move the VPN interface to it, then
# configure it and set it to UP.
set -ex
ip netns exec $NSNAME ip link set dev lo up
ip link set dev "$dev" up netns $NSNAME mtu "$link_mtu"
ip netns exec $NSNAME ip addr add "$ifconfig_local" dev "$dev" peer "$route_vpn_gateway"
ip netns exec $NSNAME ip link set "$dev" up

;;

route-up)
set -ex

# Add the IP address and turn it on. You might need these sometimes maybe.
#ip netns exec $NSNAME ip addr add "$ifconfig_local" dev "$dev" peer "$route_vpn_gateway"
#ip netns exec $NSNAME ip link set "$dev" up

# Add the default route.
ip netns exec $NSNAME ip route add default dev "$dev"

;;

down)
# Turn the network interface off
echo "disabling interface $dev..."
ip netns exec $NSNAME ip link set "$dev" down
res=$?
if [ "$res" -ne "0" ]; then
echo "disabling $dev exited with code $res, continuing..."
fi

;;
esac


+ 14
- 0
vpnns-ns.service View File

@@ -0,0 +1,14 @@
[Unit]
Description=VPN Namespace Isolation
After=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/opt/vpnwrap/nsctl.sh enable
ExecStop=/opt/vpnwrap/nsctl.sh disable
Restart=on-failure

[Install]
WantedBy=multi-user.target


+ 16
- 0
vpnns-transmission.service View File

@@ -0,0 +1,16 @@
[Unit]
Description=VPN Transmission Daemon
After=vpnns-vpn.service

[Service]
Type=forking
GuessMainPID=true
ExecStart=/opt/vpnwrap/transmissionwrap.sh enable
ExecStop=/opt/vpnwrap/transmissionwrap.sh disable
ExecReload=/opt/vpnwrap/transmissionwrap.sh reload
Restart=always
RuntimeMaxSec=86400

[Install]
WantedBy=multi-user.target


+ 12
- 0
vpnns-vpn.service View File

@@ -0,0 +1,12 @@
[Unit]
Description=VPN Namespace Networking
After=vpnns-ns.service

[Service]
Type=simple
ExecStart=/opt/vpnwrap/vpnwrap.sh
Restart=on-failure

[Install]
WantedBy=multi-user.target


+ 24
- 0
vpnwrap.sh View File

@@ -0,0 +1,24 @@
#!/bin/bash

SCRIPTPATH=$(dirname $0)
source $SCRIPTPATH/config.txt

export PATH=$SCRIPTPATH:$PATH

env

echo '==== STARTING OPENVPN ===='
openvpn \
--client \
--config $VPNCONFIG \
--ca $VPNCA \
--auth-user-pass $VPNCREDS \
--auth-retry nointeract \
--ifconfig-noexec \
--route-noexec \
--script-security 2 \
--up $SCRIPTPATH/vpnhook.sh \
--route-up $SCRIPTPATH/vpnhook.sh \
--down $SCRIPTPATH/vpnhook.sh
echo '==== EXITED OPENVPN ===='


Loading…
Cancel
Save