https://github.com/ngaro/SOSVPN
Create a VPN that tunnels over socat over ssh to evade firewalls
https://github.com/ngaro/SOSVPN
dns firewall socat ssh vpn
Last synced: 4 months ago
JSON representation
Create a VPN that tunnels over socat over ssh to evade firewalls
- Host: GitHub
- URL: https://github.com/ngaro/SOSVPN
- Owner: ngaro
- License: gpl-3.0
- Created: 2021-03-23T16:18:30.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2021-03-31T22:38:17.000Z (over 4 years ago)
- Last Synced: 2024-10-24T06:29:02.889Z (9 months ago)
- Topics: dns, firewall, socat, ssh, vpn
- Homepage:
- Size: 140 KB
- Stars: 3
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# SOSVPN
Create a VPN that tunnels over `socat` which tunnels over `ssh` to evade extremely strict firewalls__SOSVPN__ ( or SOcatSshVPN ) is a VPN-service that has 2 features that most others lack:
- Only extremely strict firewalls can block it. The only allowed traffic needed is:
- Outgoing ssh-traffic on the clientside
- Incoming ssh-traffic on the serverside
- Even a deep packet inspection firewall can't recognize the traffic as VPN-traffic, it will only see ssh-packetsAnd a couple of features (some, but not all) other VPN-software has:
- Traffic from the client meant for the internal network will stay in the internal network
- All other traffic will be sent over the VPN to the internet with the server acting as gatewayIt works by:
- Creating a virtual network
- ... that's tunnelled over a `socat`-tunnel
- ... that's tunneled over a `ssh`-tunnel
This explains the name __SOcatSshVPN__.
Not only is it just as fast as regular ssh-traffic, but by using ssh-compression you can even make it faster then many other VPN's._This is still version 0.1, here I'm only explaining how to set it up manually.
Interpreted (or compiled) code will follow later._## Example assumptions about your network setup
(Change the settings to match your usecase)
### Server
- Has a user named `someuser`
- Has the ip `1.2.3.4`
- Has a networkcard named `eths` connected to the internet
- Has a sshserver running on `tcp/22789` which is reachable from the internet.
(It doesn't matter if everything else is blocked)
- Is not yet using the virtual networkdevice `tun0` for other purposes
- Is not yet connected to a network that overlaps the `192.168.255.0/24` range
- Is not yet listening on `tcp/22001`
- Uses the DNS servers `5.6.7.8` and `9.10.11.12`
### Client
- Has the ip `13.14.15.16`
- Has a networkcard named `ethc` connected to the internet
- Can create a ssh-connection with the server.
(It doesn't matter if everything else is blocked)
- Is not yet using the virtual networkdevice `tun0` for other purposes
- Is not yet connected to a network that overlaps the `192.168.255.0/24` range
- Is not yet listening on `tcp/22002`
- Uses the gateway `13.14.0.254`
- Is on a network containing subnets `13.14.0.0/16` and `15.16.17.0/24` that has the name `mylocal.net`
- Is using the DNS servers `15.16.17.1` and `15.16.17.2`## Preliminary setup
- Install the necessary software (`iptables`, `socat`, `ssh` and `screen`) on the server.
On debian-based system this can be done with: `sudo apt install iptables socat ssh screen`
- Make sure the ssh server runs on the server:
Check `sudo systemctl status ssh` and run `sudo systemctl restart ssh` if you didn't see `active (running)` in the output.
_From now on you never need physical access to the server anymore._
- Install the necessary software (`route`, `socat`, `ssh` and `screen`) on the client.
On debian-based system this can be done with: `sudo apt install net-tools socat ssh screen`
## Creating the VPN on the client
- Run `screen` because we'll need to run different things at the same time
- Run `ssh -L 22002:127.0.0.1:22001 -p 22789 [email protected]` inside this screen session
A `ssh` session will be opened in window `0` of screen:
- We can now use this session to run commands on the server without having physical access.
- The `-L` option is used for local portwarding to make sure that when the server sends traffic to itself on `TCP/22001` it will be encrypted inside ssh-packets and end up at `TCP/22002` on the client.
- Run `screen` inside this ssh-session.
We now have a screen session on the client with 1 window (number `0`) and inside it a screen session on the server.
This also has 1 window that is numbered `0`.
This screen session is also needed because we run different things at the same time in the server.
- Run `sudo socat -d -d TCP-LISTEN:22001,reuseaddr TUN:192.168.255.1/24,up` inside window `0` of the server on screen. The result:
- A virtual network device `tun0` with ip `192.168.255.1` and netmask `255.255.255.0` will be created
- The system will start listening to `TCP/22001` for traffic from the server itself and interpret it as traffic from a virtual network with the descriptions above.
- This traffic will be sent to the system over `tun0`
- The portforwarding means that it's actually listening to traffic sent to `TCP/22002` on the client by the client itself
- It works bi-directional, so traffic sent out by the system to a system on `192.168.255.0/24` will leave using `tun0`, will be packed into TCP-packets and these will be tunneled over the ssh-connection to finally end up at `TCP/22002` on the client.
(`-d -d` is used for reasonably verbose debug info in case something goes wrong)
- Press __ctrl-a__ followed by a __a__ and a __c__ to create another window (number `1`) in the screen session on the server.
We will use this to make sure that traffic from the client meant for the outside world will be passed on by the system and is NAT-ed:
```
sudo iptables -t nat -A POSTROUTING -s 192.168.255.0/24 -j MASQUERADE
sudo iptables -A FORWARD -i tun0 -o eths -j ACCEPT
sudo iptables -A FORWARD -o tun0 -i eths -j ACCEPT
```
- Press __ctrl-a__ followed by a __c__ to create another window (number `1`) in the screen session on the client.
Run `sudo socat -d -d TCP:127.0.0.1:22002 TUN:192.168.255.2/24,up` here. This will create the other endpoint of the tunnel.
Note that the ip is different (`192.168.255.2`) but still in the same network as the one on the server (`192.168.255.0/24`).
This is necessary to make sure that communication is possible.
- Press __ctrl-a__ followed by a __c__ to create another window (number `1`) in the screen session on the client.
We will use this make sure traffic is routed correctly:
```
# Make sure that the server itself is not routed over the VPN:
sudo route add 1.2.3.4 gw 13.14.0.254
# Make sure that the traffic sent to the gateway is sent out using the real network device:
sudo route add 13.14.0.254 dev ethc
# Make sure that traffic meant for our network stays in our network:
for net in 13.14.0.0/16 15.16.17.0/24 ; do sudo route add -net $net gw 13.14.0.254 ; done
# Make sure that all other traffic is sent over the VPN instead of the regular network
sudo route add default gw 192.168.255.1 && sudo route del default gw 13.14.0.254
```
### Setup DNS for the VPN
You probably want your client to resolve internal names using the dnsservers on your network, and the rest of the network using external dnsservers (the ones on your server).
You can do this like this:
- Install bind (`sudo apt install bind9` on debian-based systems)
- Add the following to `/etc/bind/named.conf.local`:
```
zone "mylocal.net" IN {
type forward;
forwarders {
15.16.17.1; 15.16.17.2;
};
};
```
- Place the following in the `options {};` section in `/etc/bind/named.conf.options`:
```
forwarders { 5.6.7.8; 9.10.11.12; };
allow-recursion { 127.0.0.1; };
querylog yes;
```
- Restart your local dns-server: `systemctl restart named`
- Make sure you use `127.0.0.1` as dns-server. (The "clean" procedure differs from system to system, the "ugly" sollution of commenting everything in `/etc/resolv.conf` and adding the line `nameserver 127.0.0.1` should work everywhere)
## Destroying the VPN
The short version: Use all the steps you used to create the VPN in reverse.
The long version:
- Attach the screen session with `screen -r` if it's no longer on your terminal, jump to window `2` with __ctrl-a__ followed by __2__.
You can reset the routing on the client here:
```
sudo route del default gw 192.168.255.1 && sudo route add default gw 13.14.0.254
for net in 13.14.0.0/16 15.16.17.0/24 ; do sudo route del -net $net gw 13.14.0.254 ; done
sudo route del 13.14.0.254 dev ethc
sudo route del 1.2.3.4 gw 13.14.0.254
exit
```
- Jump to window `0` with __ctrl-a__ followed by __0__ where the screen session in the ssh-session is running.
Now jump now to window `1` in this screen session with __ctrl-a__ followed by __a__ followed by __1__ and reset `iptables` here:
```
sudo iptables -t nat -D POSTROUTING -s 192.168.255.0/24 -j MASQUERADE
sudo iptables -D FORWARD -i tun0 -o eths -j ACCEPT
sudo iptables -D FORWARD -o tun0 -i eths -j ACCEPT
exit
```
- You will now end up in window `0` of the screen-session on the server, press __ctrl-c__ here to kill socat. This will also kill the endpoint of the tunnel at the client. Now run the `exit` command a couple of times until all windows in both screen sessions are killed.
- Use your original DNS configuration again by:
- Stopping bind with `systemctl stop named`
- Changing your dnsservers back to `15.16.17.1` and `15.16.17.2`.
Again, multiple ways to do this are possible. Placing `nameserver 15.16.17.1` and `nameserver 15.16.17.2` in `/etc/resolv.conf` and commenting out the rest should work as "ugly" solution.
SOSVPN is created by Nikolas Garofil and licensed under GPLv3, see the `License` file for details.