I’m researching using Linux VMs as an airtight internet+VPN provider + actually airtight killswitch.
I’ve set up my VPN via OpenVPN in Debian, and told the network connection to “automatically connect to VPN when using this connection”.
But how can I set up a killswitch?
Thought I’d set up UFW firewall to only allow traffic through VPN (on tun0):
ufw default deny outgoing
ufw default deny incoming
ufu allow out to {VPN DOMAIN} port xxxx proto udp ; - you can have an IP here but it changes
ufw allow out on tun0 from any to any
Except this only works for IPs. UFW is just an interface to the linux iptables, which is OSI layer 3+4 (Network + Transport). I/we need Layer 7 (Application). [source]
The VPN has dynamic IPs to avoid itself being blocked by ISPs etc., so manually assigning one IP can change at any moment. Trying to assign whole giant IP ranges beats the privacy/security purpose entirely.
How can we get a linux system that:
only allows traffic on an IP if it’s assigned to my VPN’s Domain (proxies + application layer domain filtering??)
has a normally functioning firewall
must be able to auto(re)connect to VPN any time (when IP changes)
[Edit] I repeat: killswitch means: must not connect or be reached at any stage to/by anything other than the VPN
PS: In PFSense you can totally set it up to only work if it’s connected to OpenVPN. But PFSense doesn’t like Wifi adapters as WAN
Need to allow for inbound established connections on tun0. Dunno how to do it on ufw, but the iptables equivalent is iptables -A INPUT -i tun0 -m state --state RELATED,ESTABLISHED -j ACCEPT
Edit: Ignore my comment on removing the 3rd rule. Have to be able to make that initial connection somehow. Looks like you have to hard code the IP address, unless you want to leak your DNS for the inital lookup and nothing else. Could you maybe make a list of every single IP address your VPN provider makes available, and just randomly choose one everytime you connect?
Usually a Layer 7 ‘firewall’ is a device that has intrusion detection & prevention, which captures traffic at high speeds and matches it against a threat database. Snort is an open source example: https://www.snort.org/
It sounds like you want to connect snort to your killswitch.
you could use top to find the process number then use killall [process or process number] You could probably write a little bash script to killall process, give it a click and kablewie.
next, allow on tun0 to require traffic to go through your firewall.
ufw allow out on tun0 from any to any
ufw allow in on tun0 from any to any
Next, allow on your VPN IP (which we found above).
ufw allow in from $(getent hosts your.vpn.domain | awk '{ print $1 }') to any
ufw allow out from any to $(getent hosts your.vpn.domain | awk '{ print $1 }')
That doesn’t work. I know how to get an IP from a domain. And I can paste it instead of {VPN DOMAIN} in the example in the post. But consider this: I start up the machine, the machine needs to make a connection to the VPN -only-. But the dynamic VPN domain has changed its IP since last time, and now all I know is its domain name.
Or consider this: I am connected to a VPN IP, the VPN provider changes its IP because it’s dynamic, and I suddenly get logged out from the VPN/internet. How do I get a new IP? Can I run getent hosts while everything is blocked? All I know is the domain name and I can’t (don’t want to) expose myself to the internet if it’s not through the VPN.
So yeah, I/we need some wizard-level shit. Or some proxy + layer 7 filtering or something.
I don’t get when/how that happens. If the script needs to find the IP belonging to a domain, then it needs access to the internet. How can I make sure the machine only has access to that domain and no other parts of the internet can reach or be reached by it?
I need to only be able to do one thing: use for example OpenDNS , to connect to my VPN via its domain name.
If you have traffic and then switch between vpn and non vpn or the other way around, it’s pretty much as bad as if you weren’t using vpn at all in the first place, privacy/tracking/security wise.
ahh so you want a full traffic stop the moment VPN is down
Edit: below
then it seems @SgtAwesomesauce has it, a script that disallows traffic not going over VPN ran before or as the VPN start up script. when vpn fails. no other route is possible untill you run the script to re allow traffic off of vpn
The additional problem is that OP wants the VPN to never connect to anything more than the IP of his server, but it’s on a Dynamic IP. This means he’s got to do a DNS lookup. While that’s simple to do, and limit to, DNS is not a secure solution.
I’m thinking the best option is to attempt to get a static IP for the VPN server (I’m assuming it’s self-hosted).
It’s not a self-hosted VPN. I’m trying to make a fullproof setup for any VPN. My current VPN is dynamic IP, as are most VPNs since they want to not be blocked by ISPs etc.
In what ways can DNS be not secure? Someone can spoof the DNS server? Someone can spoof the domain stored on the DNS server? I’m fine with the possibility of hitting a spoofed one, as long as I can tell the difference and only connect if I can prove it’s the right one.
Basically the default behaviour of most VPN providers’ own custom VPN clients is for you to connect using their domain name, no?
PS: I don’t know enough about linux to know what to use to limit traffic to a domain.
[EDIT] PFSense connects to VPN via domain names and I didn’t see any warning against that.
[Edit2] The VPN provides openvpn certificate and keys, so in my limited knowledge I don’t see how DNS is not secure. At most I can divulge my username and encrypted password.
You just need to do a DNS lookup for the VPN before you connect to it, so you can have your script change the firewall rules to allow you to talk to whatever dns server you want to use, resolve the ip, set the firewall back, connect to the VPN using the resolved ip.
Or you could install a local dns server and configure a DNS override for your VPN domain name so that only requests for that domain go to an external server which you allow over your normal connection and everything else is done over the VPN.
Okay, so one suggestion is to build a script that:
makes sure internet is off if firewall is off
– (and firewall makes sure internet is off if VPN is off)
if vpn is not connected:
– disable firewall
– connect to internet ONLY to get new vpn IP
— ^ HOW do you guarantee only connections to and from that domain lookup are possible?
– reconfigure firewall with new IP, only allow VPN tun0 connection + that IP
– start firewall
connect to vpn
It seems like I might as well not have a firewall VPN IP rule in the first place if I need to break the firewall to do the DNS lookup.
As I understand it, the only option is an application-level domain-based firewall or proxy or something. Like a “On all except tun0, only allow connections to my.vpn.domain as reported by OpenDNS” rule.
So how do I do that ^ ? Anyone have software recommendations / guide links?
I would probably disable forwarding while the vpn is set up. That prevents the network from using the router until is connected. The firewall rules to do that would be something like:
# drop packets from the lan
$ iptables -A FORWARD -i lan0 -j DROP
# start vpn
# enable packets from the lan by deleting the drop rule
$ iptables -D FORWARD -i lan0 -j DROP