Gentoo, Relakks VPN, NAT and Firewall

From Joyrex Wiki

Jump to: navigation, search

Contents

Preamble

Relakks is a VPN hoster that basically gives you a swedish IP. The intention is you use this for the your Internet traffic to prevent spying/records by your local ISP, government, whatever. The encrypted VPN tunnel means your ISP will only see you talk to the VPN server in Sweden, they cannot see what sites you're really going to.

Keep in mind that the encrypted VPN tunnel ends in Sweden. Wherever the traffic goes from there is just normal over the internet. If you're not using SSL, then someone could listen in on the server side and see you hit them.

I was running Ubuntu Feisty, but was having problems getting it all going, especially with NetworkManager, which may possibly be screwed for PPTP VPNing anyways. I found a tutorial for using it on Gentoo and thought I'd give it a shot (links below). This PC is also my default router/connection to the internet, as well as acting as a dhcp/nat server for my internal network. This requires some work to get it all working together. Here's how I did it.

I'm now running Gentoo with 2.6.21 gentoo-sources. eth0 is my connection to the internet (Neighborhood Comcast connection.. it's DHCP :( ). eth1 is my internal network running on 192.168.1.0/255.255.255.0.

Caveats: This probably isn't optimized. My iptables script is quick and dirty with no error catching. My iptables rules are probably redundant at certain points. My kernel modules aren't probably all needed. My ppp options.. well.. they're probably OK.


Gentoo System

Kernel Config

The kernel needs various things. I'm not sure it absolutely *needs* all of them, but it doesn't hurt (besides compile time):

Code:
Loadable module support  ---> 
 [*] Enable loadable module support
 [*]   Automatic kernel module loading
Networking  ---> 
 [*] TCP/IP networking
  <*>   INET: socket monitoring interface                  
  [*] Network packet filtering framework (Netfilter)  --->
   Core Netfilter Configuration  --->
    <*> Netfilter netlink interface
    <*> Netfilter connection tracking support
    [*] Connection tracking flow accounting
    [*] Connection mark tracking support
    [*] Connection tracking events (EXPERIMENTAL)
    <M> PPtP protocol support
    <M> Connection tracking netlink interface (EXPERIMENTAL)
    <*> Netfilter Xtables support (required for ip_tables)
    <M>   "CLASSIFY" target support
    <M>   "MARK" target support
    <M>   "NFQUEUE" target Support
    <M>   "NFLOG" target support
    <M>   "TCPMSS" target support
    <M>   "comment" match support
    <M>   "DCCP" protocol match support
    <M>   "DSCP" match support
    <M>   "ESP" match support
    <M>   "length" match support
    <M>   "limit" match support
    <M>   "mac" address match support
    <M>   "mark" match support
    <M>   IPsec "policy" match support
    <M>   Multiple port match support
    <M>   "pkttype" packet type match support
    <M>   "quota" match support
    <M>   "realm" match support
    <M>   "sctp" protocol match support (EXPERIMENTAL)
    <M>   "state" match support
    <M>   "statistic" match support
    <M>   "string" match support
    <M>   "tcpmss" match support
    <M>   "hashlimit" match support
   IP: Netfilter Configuration  --->
    <*> IPv4 connection tracking support (required for NAT)
    [*]   proc/sysctl compatibility with old connection tracking
    <M> IP tables support (required for filtering/masq/NAT)
    <M>   IP range match support
    <M>   TOS match support
    <M>   recent match support
    <M>   ECN match support
    <M>   AH match support
    <M>   TTL match support
    <M>   Owner match support
    <M>   address type match support
    <M>   Packet filtering
    <M>     REJECT target support
    <M>   LOG target support
    <M>   ULOG target support
    <M>   Full NAT
    <M> MASQUERADE target support
    <M> REDIRECT target support
    <M> NETMAP target support
    <M> SAME target support
    <M> Basic SNMP-ALG support (EXPERIMENTAL)
    <M> Packet mangling 
    <M>   TOS target support
    <M>   ECN target support
    <M>   TTL target support
    <M> raw table support (required for NOTRACK/TRACE)
Device Drivers  --->
 Network device support  --->
   <M>   PPP (point-to-point protocol) support                                                    
   <M>     PPP support for async serial ports      
   <M>     PPP support for sync tty ports          
   <M>     PPP Deflate compression                 
   <M>     PPP BSD-Compress compression            
   <M>     PPP MPPE compression (encryption) (EXPERIMENTAL)
   <M>     PPP over Ethernet (EXPERIMENTAL)                
   <M>     PPP over ATM

As I've said: it's probably not all necessary, but it works for me ;)

Package Config

Gentoo has to have the following packages installed:

USE="mppe-mppc" emerge ppp pptp-client dhcp iptables dnsmasq


TODO: DHCP Config

  • DHCP should be set up to use the server/router/dhcp server as the first DNS server


TODO: DNSMasq Config

  • DNSMasq needs no real config. It will pull from the current resolv.conf, which is handy.


PPP

PPP Configuration

Start off by creating the Relakks connection:

pptp-command

Give it the following info:

Connection Profile: Other
Tunnel Name: Relakks
Server IP: pptp.relakks.com
Route: Just hit enter here.  Routes are done manually later
Local Name: <relakks user name>
Remote Name: Relakks

Go to the Relakks peers file (which was just created) and put in a couple extra lines. Set it up to look like: {{Box File|/etc/ppp/peers/Relakks|

name <relakks username>
remotename Relakks
pty "pptp pptp.relakks.com --nolaunchpppd"
file /etc/ppp/options.pptp

Put one of the Relakks IPs in your /etc/hosts file. Get the list of IPs you can use from:

dig pptp.relakks.com

Use one of the ones in the ANSWER section:

File: /etc/hosts
83.233.181.2       pptp.relakks.com

Set up the PPTP options you'll use for your connection:

File: /etc/ppp/options.pptp

lock noauth refuse-eap nobsdcomp nodeflate noaccomp ##noccp nopcomp novj novjccomp mtu 1400 mru 1458 #lcp-echo-failure 10 lcp-echo-interval 30 mppe stateless,no40,no56 usepeerdns

Set up the system run the ip-up.local and ip-down.local scripts, where we'll be running our route (and firewall) commands:

File: /etc/ppp/ip-up
[ -f /etc/ppp/ip-up.local ] && . /etc/ppp/ip-up.local "$@"

Move this line from the bottom of the file to the top

Touch and chmod the ip-up.local, ip-down.local, and apply-iptables.sh files. The apply-iptables.sh file is a script that will be used later for NAT and firewalling later (see below):

touch /etc/ppp/ip-up.local
touch /etc/ppp/ip-down.local
touch /etc/ppp/apply-iptables.sh
chmod 755 /etc/ppp/ip-*.local
chmod 755 /etc/ppp/apply-iptables.sh

Now, set up the ip-up.local file. This is purely a bash script that will be run upon connection. We're going to use a slight bit of code here to get the default gateway of our internet connection. Since I'm on a DHCP connection, if my internet connection drops in and out, I could have a new gateway. It'd suck to have to update this all manually. If your default internet connection isn't on eth0, you'll need to change eth0 to whatever in the two spots below.

The whole point of this file is to route everything through the VPN. It has to set up a static route to the normal internet connection interface so the VPN control packets still go through, though:

File: /etc/ppp/ip-up.local
# get the default gw of our internet connection
DEFAULT_GW=`route -n | grep UG | grep eth0 | awk {'print $2'}`

route add -host pptp.relakks.com gw $DEFAULT_GW dev eth0
route del -host pptp.relakks.com dev ppp0
route del default
route add default ppp0
/etc/ppp/apply-iptables.sh ppp0

Now let's set up the default ip-down.local file. Once again, if your normal internet connection is not on eth0, update the below appropriately:

File: /etc/ppp/ip-down.local
# get the default gateway of our internet connection
DEFAULT_GW=`route -n | grep eth0 | grep UGH | awk {'print $2'}`

route del default
route add default gw $DEFAULT_GW dev eth0
route del -host pptp.relakks.com
/etc/ppp/apply-iptables.sh eth0

Finally, let's configure the chap-secrets file. This file is where we put in the connection username and password:

File: /etc/ppp/chap-secrets
<relakks username> Relakks <relakks password> *

Make sure the file isn't readable by normal users! The password is plaintext!:

chmod 600 /etc/ppp/chap-secrets

PPP Testing

You should be able to test this out now by running:

pon Relakks

After about 5 seconds, run:

ifconfig
route -n
cat /etc/resolv.conf

ifconfig should show a ppp0 entry with an IP and with normal send/transmit amounts (there's a way to screw up where the TX gets to almost a gig in transfer and then dies, all in about 30 seconds. This is due to not having a proper static route set for pptp.relakks.com). Route -n should show your default gw being ppp0. /etc/resolv.conf should show Relakk's DNS servers (not yours, although it may keep the search string). If you have problems here, double-check all your files. For debugging, you can start the connection with:

pon Relakks debug
tail -f /var/log/messages

Watch the logs and google the error messages if your connection fails. The PPTP-Client Diagnosis Page is also very, very helpful at this stage. Going forward from this point assumes you can use the VPN successfully.

For now, disable the VPN connection:

poff Relakks

Your route and resolv.conf should return to normal.

Set up a net.ppp0 to start on boot (assuming you want to):

ln -s /etc/init.d/net.lo /etc/init.d/net.ppp0
rc-update add net.ppp0 default

Edit the /etc/conf.d/net.ppp0 file to tell it to use the Relakks VPN, and to reconnect on disconnection:

File: /etc/conf.d/net.ppp0
config_ppp0=( "ppp" )
pppd_ppp0=(
        "persist"
        "call Relakks"
        "holdoff 10"
)
link_ppp0="pty \"pptp pptp.relakks.com --nolaunchpppd\""

You should now be able to start and stop the VPN with:

/etc/init.d/net.ppp0 start
# test here
/etc/init.d/net.ppp0 stop


Firewall

Note: From here on out, I'll be using eth0 as my normal internet connection and ppp0 as my ppp connection. Make sure you change this to your own interface if it's something different.

There are two parts for the firewall. The first part walks you through what you set up in iptables, and why. The second part just goes directly to how I do it with my Relakks connection. The second part is purely my style. If you have a better idea or want to do it differently, by all means, go ahead. Also note, the iptables scripts could probably be optimized. This does work, though. You can always save your current iptables setup with:

iptables-save /root/iptables-rules

Firewall Step 1: Manual Configuration

Start the VPN:

/etc/init.d/net.ppp0 start

Ensure you can still access the internet.

We should set up the system to allow IP forwarding. This is done by running:

echo 1 > /proc/sys/net/ipv4/ip_forward

Once the machine reboots, that setting will be lost. To make it load every time, edit /etc/sysctl.conf and add the following line to the bottom:

File: /etc/sysctl.conf
net.ipv4.ip_forward = 1

We want to start with a fresh firewall, so to begin:

iptables -F
iptables -t nat -F
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT

This will flush all the tables. If you were currently NAT-ing anything, you're not anymore! This makes the default policies ACCEPT, too.

The first thing we want to add to the new firewall is a rule suggested by the Gentoo devs. This may help you, depending on your MTU size:

iptables -I FORWARD 1 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

Next you want to add the commands to allow the VPN control traffic to go in and out:

iptables -I INPUT -i eth0 -p 47 -m state --state ESTABLISHED -j ACCEPT
iptables -I OUTPUT -o eth0 -p 47 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -I INPUT -i eth0 -p tcp --sport 1723 -m state --state ESTABLISHED -j ACCEPT
iptables -I OUTPUT -o eth0 -p tcp --dport 1723 -m state --state NEW,ESTABLISHED -j ACCEPT

Now we will add the NAT stuff. This will allow machines inside the network use you as the default router:

iptables -t nat --append POSTROUTING -o ppp0 -j MASQUERADE
iptables -A FORWARD -i eth1 -j ACCEPT

That's it. Basic NAT is done. You should now be able to surf the internet from internal machines using the VPN. Keep in mind you're still completely open though, no packets get rejected or dropped. That's not cool, so let's move on to that.

Before we set the default policies to DROP, we want to make sure the stuff we need to get through, can get through. First, allow all traffic from the internal networks. Replace eth1 with your internal network interface, if necessary. Also add any other interfaces you have that aren't external:

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth1 -j ACCEPT

Now, allow in specific traffic coming from the VPN. Existing connections and ICMP packets (at one a second) are fine. I also want bittorrent (port 6881) traffic to be accepted through the VPN. You'll have to replace IP_ADDRESS with the IP Address of your VPN connection:

iptables -A INPUT -d IP_ADDRESS -i ppp0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -d IP_ADDRESS -i ppp0 -p icmp -m icmp --icmp-type 8 -m limit --limit 1/sec --limit-burst 3 -j ACCEPT
iptables -A INPUT -d IP_ADDRESS -i ppp0 -p tcp -m tcp --dport 6881 --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j ACCEPT

Now that I think about it, it'd be good to allow some traffic to go through eth0 as well. I want it to be open for ssh and http traffic. You'll have to replace ETH0_IP_ADDRESS with the IP Address of your Internet connection (normal, not VPN):

iptables -A INPUT -d ETH0_IP_ADDRESS -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -d ETH0_IP_ADDRESS -i eth0 -p icmp -m icmp --icmp-type 8 -m limit --limit 1/sec --limit-burst 3 -j ACCEPT
iptables -A INPUT -d ETH0_IP_ADDRESS -i eth0 -p tcp -m tcp --dport 22 --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j ACCEPT
iptables -A INPUT -d ETH0_IP_ADDRESS -i eth0 -p tcp -m tcp --dport 80 --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j ACCEPT

If you want to add other things to either ppp0 traffic or eth0, just copy the above lines that use dport and set it appropriately. Also make sure you have the proper interface (-i) and IP address (-d) interface specified for the interface you want open the port on. For example, it wouldn't make sense for me to open bittorrent to eth0, because I want that to all go through the VPN. Likewise, I don't want to ssh to my own machine through the VPN tunnel, I'll just hit it directly (ssh is already secure).

Now, we'll want to forward everything coming from our internal network onwards. Let's do that:

iptables -A FORWARD -i eth1 -j ACCEPT

We'll also want to let data coming in over the internet (from an established connection) come back to the internal machine:

iptables -A FORWARD -d 192.168.1.0/255.255.255.0 -i ! lo -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT

Finally, we'll want to let data out from all interfaces:

iptables -A OUTPUT -o lo -j ACCEPT
iptables -A OUTPUT -o eth1 -j ACCEPT
iptables -A OUTPUT -o eth0 -j ACCEPT
iptables -A OUTPUT -o ppp0 -j ACCEPT

Alright, all our tables are in. Let's see how successful we were. Set the default policy to DROP.

iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

Success, hopefully. If your connection stops working for any machine, something's screwed. It's hard to list what it could be, you may have to post somewhere for help, use google, or man iptables. To turn everything back to ACCEPT by default:

iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT

You may have to reboot though. If PPP dies for some reason, it can get confused (restart as ppp1, or not restart at all). It's easier to start with a clean slate.

Firewall Step 2: Setting it up to automatically update

So it's all working, but if the VPN goes down or down and back up with a new IP, this won't work. Thankfully, /etc/ppp/ip-up.local and /etc/ppp/ip-down.local exist ;). We used these files before to set the routes on connect and disconnect, and we can also use them for firewall rules.

Save your current iptables setup. Do this with:

iptables-save > /etc/ppp/iptables-rules

Now edit that file. Everywhere there's a eth0 IP address reference, you want to change it to ETH0_IP_ADDRESS. Everywhere your VPN IP is referenced, change it to IP_ADDRESS. At the top of the file (the -A POSTROUTING -o ppp0 -j MASQUERADE command), change ppp0 to INTERFACE_NAME. Make sure all the references are changed correctly. Failure to do so will end up with your iptables rules being screwed. As an example, here is a /etc/ppp/iptables-rules file from what we did above:

File: /etc/ppp/iptables-rules
# Generated by iptables-save v1.3.7 on Tue May  8 22:15:05 2007
*nat
:PREROUTING ACCEPT [6286:458263]
:POSTROUTING ACCEPT [2:120]
:OUTPUT ACCEPT [113:7226]
-A POSTROUTING -o INTERFACE_NAME -j MASQUERADE 
COMMIT
# Completed on Tue May  8 22:15:05 2007
# Generated by iptables-save v1.3.7 on Tue May  8 22:15:05 2007
*filter
:INPUT DROP [596:90941]
:FORWARD DROP [0:0]
:OUTPUT DROP [123:58828]
-A INPUT -i eth0 -p tcp -m tcp --sport 1723 -m state --state ESTABLISHED -j ACCEPT 
-A INPUT -i eth0 -p gre -m state --state ESTABLISHED -j ACCEPT 
-A INPUT -i lo -j ACCEPT 
-A INPUT -i eth1 -j ACCEPT 
-A INPUT -d IP_ADDRESS -i ppp0 -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -d IP_ADDRESS -i ppp0 -p icmp -m icmp --icmp-type 8 -m limit --limit 1/sec --limit-burst 3 -j ACCEPT 
-A INPUT -d IP_ADDRESS -i ppp0 -p tcp -m tcp --dport 6881 --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j ACCEPT 
-A INPUT -d ETH0_IP_ADDRESS -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -d ETH0_IP_ADDRESS -i eth0 -p icmp -m icmp --icmp-type 8 -m limit --limit 1/sec --limit-burst 3 -j ACCEPT 
-A INPUT -d ETH0_IP_ADDRESS -i eth0 -p tcp -m tcp --dport 22 --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j ACCEPT 
-A INPUT -d ETH0_IP_ADDRESS -i eth0 -p tcp -m tcp --dport 80 --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j ACCEPT 
-A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu 
-A FORWARD -i eth1 -j ACCEPT 
-A FORWARD -d 192.168.1.0/255.255.255.0 -i ! lo -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A OUTPUT -o eth0 -p tcp -m tcp --dport 1723 -m state --state NEW,ESTABLISHED -j ACCEPT 
-A OUTPUT -o eth0 -p gre -m state --state NEW,ESTABLISHED -j ACCEPT 
-A OUTPUT -o lo -j ACCEPT 
-A OUTPUT -o eth1 -j ACCEPT 
-A OUTPUT -o eth0 -j ACCEPT 
-A OUTPUT -o ppp0 -j ACCEPT 
COMMIT
# Completed on Tue May  8 22:15:05 2007

Obviously the time and date will be different. You now have a basic template you can use to apply dynamic IPs and interfaces to. You just need a wrapper to update the entries with what is current at the time of execution. This is where /etc/ppp/apply-iptables.sh comes in. This is one of the files we touched and chmoded to 755 earlier in the PPP setup phase. Also, both ip-up.local and ip-down.local run it, passing the newly-active default interface to the script.

File: /etc/ppp/apply-iptables.sh
#!/bin/bash

INTERFACE_NAME=$1
IP_ADDRESS=`ifconfig | grep -A 1 $INTERFACE_NAME | grep inet | awk {'print $2'} | cut -d: -f2`
ETH0_IP_ADDRESS=`ifconfig | grep -A 1 eth0 | grep inet | awk {'print $2'} | cut -d: -f2`

cp /etc/ppp/iptables-rules /tmp/iptables-rules-tmp
perl -pi -e "s/INTERFACE_NAME/$INTERFACE_NAME/g" /tmp/iptables-rules-tmp
perl -pi -e "s/ETH0_IP_ADDRESS/$ETH0_IP_ADDRESS/g" /tmp/iptables-rules-tmp
perl -pi -e "s/IP_ADDRESS/$IP_ADDRESS/g" /tmp/iptables-rules-tmp
iptables -F
iptables -t nat -F
iptables-restore < /tmp/iptables-rules-tmp

This script will:

  • Take the current interface
  • Grab the current interface's IP
  • Grab the normal internet connection IP
  • Copy the template iptables rules to /tmp
  • Update the copied file with the new values
  • Flush the current iptables rules
  • Load the new rules with iptables-restore

Now, if your iptables-rules template file is bad, or if the script breaks for some reason, your system is left in a pretty screwed state. The VPN connection may/may not be up. Your route could be screwed. Firewall/NAT could be screwed. If you know how to fix it, give it a shot. If you don't:

rc-update del net.ppp0 default

and reboot. Then you can manually start the connection on reboot and debug and try again.


Credits/Links

Most of this was put together from various sources. They are:

Personal tools