3

I have a linux firewall setup as my home network gateway that is correctly leasing IP addresses to devices on my network, and those devices have internet access.

I also setup OpenVPN on the same machine and it's up and running and doling out IP addresses and I'm able to access the VPN from my phone. However, devices on the VPN do not have internet access and I can't figure out why.

Here are the iptables rules I'm using:

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]

# enp2s0 is WAN interface, enp1s0 is LAN interface, tun0 is vpn interface
-A POSTROUTING -o enp2s0 -j MASQUERADE
-A POSTROUTING -s 10.8.0.0/8 -o enp2s0 -j MASQUERADE

COMMIT

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]

# block invalid packets
-A PREROUTING -m conntrack --ctstate INVALID -j DROP

# block fragmented packets (may be unnecessary)
#-A PREROUTING -f -j DROP

# block new packets that are not SYN
-A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROP

# block uncommon MSS values
-A PREROUTING -p tcp -m conntrack --ctstate NEW -m tcpmss ! --mss 536:65535 -j DROP

# block packets with bogus TCP flags
-A PREROUTING -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
-A PREROUTING -p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
-A PREROUTING -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
-A PREROUTING -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
-A PREROUTING -p tcp --tcp-flags FIN,ACK FIN -j DROP
-A PREROUTING -p tcp --tcp-flags ACK,URG URG -j DROP
-A PREROUTING -p tcp --tcp-flags ACK,FIN FIN -j DROP
-A PREROUTING -p tcp --tcp-flags ACK,PSH PSH -j DROP
-A PREROUTING -p tcp --tcp-flags ALL ALL -j DROP
-A PREROUTING -p tcp --tcp-flags ALL NONE -j DROP
-A PREROUTING -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
-A PREROUTING -p tcp --tcp-flags ALL SYN,FIN,PSH,URG -j DROP
-A PREROUTING -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP

# block packets from private subnets (spoofing)
-A PREROUTING -s 224.0.0.0/3 -j DROP
-A PREROUTING -s 169.254.0.0/16 -j DROP
-A PREROUTING -s 172.16.0.0/12 -j DROP
-A PREROUTING -s 192.0.2.0/24 -j DROP
#-A PREROUTING -s 192.168.0.0/16 -j DROP
-A PREROUTING -s 10.0.0.0/8 -j DROP
-A PREROUTING -s 0.0.0.0/8 -j DROP
-A PREROUTING -s 240.0.0.0/5 -j DROP
-A PREROUTING -s 127.0.0.0/8 ! -i lo -j DROP

COMMIT

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
# Service rules

# Log all input and forward connections
-A INPUT -j LOG
-A FORWARD -j LOG

# basic global accept rules - ICMP, loopback, traceroute, established all accepted
-A INPUT -s 127.0.0.0/8 -d 127.0.0.0/8 -i lo -j ACCEPT
#-A OUTPUT -o lo -j ACCEPT
-A INPUT -p icmp -j ACCEPT
# the below rule might require ,RELATED if things fail, such as OpenVPN
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#-A INPUT -m conntrack --ctstate RELATED -j ACCEPT
#-A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT

# enable traceroute rejections to get sent out
-A INPUT -p udp -m udp --dport 33434:33523 -j REJECT --reject-with icmp-port-unreachable

# DNS - accept from LAN and VPN
-A INPUT -i enp1s0 -p tcp --dport 53 -j ACCEPT
-A INPUT -i enp1s0 -p udp --dport 53 -j ACCEPT
-A INPUT -i tun0 -p tcp --dport 53 -j ACCEPT
-A INPUT -i tun0 -p udp --dport 53 -j ACCEPT

# SSH - accept from LAN and VPN; note that SSH on this machine uses a non-standard port
-A INPUT -i enp1s0 -p tcp --dport 123 -j ACCEPT
-A INPUT -i tun0 -p tcp --dport 123 -j ACCEPT

# OpenVPN - accept from WAN; note that OpenVPN on this machine uses port 443 to try to get past client network filtering
-A INPUT -i enp2s0 -p tcp --dport 443 -j ACCEPT
#-I INPUT -i tun0 -j ACCEPT
-I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# DHCP client requests - accept from LAN and VPN
-A INPUT -i enp1s0 -p udp --dport 67:68 -j ACCEPT
-A INPUT -i tun0 -p udp --dport 67:68 -j ACCEPT

# drop invalid packets
-A INPUT -m conntrack --ctstate INVALID -j DROP

# drop connections from hosts that have more than 80 established connections (prevents connection attacks)
-A INPUT -p tcp -m connlimit --connlimit-above 80 -j REJECT --reject-with tcp-reset

# limit the new TCP connections that a client can establish per second, reducing connection attacks
-A INPUT -p tcp -m conntrack --ctstate NEW -m limit --limit 60/s --limit-burst 20 -j ACCEPT
-A INPUT -p tcp -m conntrack --ctstate NEW -j DROP

# block port scanning
-N port-scanning
-A port-scanning -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s --limit-burst 2 -j RETURN
-A port-scanning -j DROP

# block HTTPS ads
#-A INPUT -p udp --dport 80 -j REJECT --reject-with icmp-port-unreachable
#-A INPUT -p tcp --dport 443 -j REJECT --reject-with tcp-reset
#-A INPUT -p udp --dport 443 -j REJECT --reject-with icmp-port-unreachable

# drop all other inbound traffic
-A INPUT -j DROP

# Forwarding rules

# forward packets along established/related connections
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# forward from LAN (enp1s0) to WAN (enp2s0)
-A FORWARD -i enp1s0 -o enp2s0 -j ACCEPT

# forward from VPN (tun0) to WAN (enp2s0)
-A FORWARD -i tun0 -o enp2s0 -j ACCEPT

# drop all other forwarded traffic
-A FORWARD -j DROP

COMMIT

What am I missing that would allow devices on the VPN to access the internet?

2 Answers 2

0

Sounds like your clients (if they are Android/iOS) have the Seemless Tunnel option enabled, or the iptables NAT-enabling command is screwing with the tunnel (unlikely). Check with your blocking rules to make sure they aren't blocking the wrong subnet.

Also (if your server is running a version of Linux) make sure IP forwarding is enabled in the kernel. To do this (run as administrator):

echo 1 > /proc/sys/net/ipv4/ip_forward
Windows has a different method of enabling IP forwarding. This article should help you there.

1
  • I disabled Seamless Tunnel and then checked that IP forwarding was enabled. Neither resolved the issue. I'll check my blocking rules and report back.
    – rosstripi
    Jun 17, 2018 at 13:46
0

I did - what you are trying - in a virtual machine. I created two machines, machine A with two ethernet devices. One device connected to the internet, the other connected to the second virtual machine B.

The following lines are all i needed to make machine B able to use the Internet or VPN connection from machine A.

vm1@vm1:~$ cat firewall01.sh 
#!/bin/bash

#sudo iptables -t nat -A POSTROUTING -o enp0s3 -j MASQUERADE
#sudo iptables -A FORWARD -i enp0s3 -o enp0s8 -m state --state RELATED,ESTABLISHED -j ACCEPT
#sudo iptables -A FORWARD -i enp0s8 -o enp0s3 -j ACCEPT


sudo iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
sudo iptables -A FORWARD -i tun0 -o enp0s8 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i enp0s8 -o tun0 -j ACCEPT

Also i did edit /etc/sysctl.conf

# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

After that run sudo sysctl -p to let the changes take effect imediately.

  • enp0s3 is the ethernet device connected to the internet.
  • enp0s8 is the ethernet device connected to the local machine B.
  • tun0 is the ethernet device created from openvpn

For testing purpose, i set my default policy to accept.

vm1@vm1:~$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination 

The openvpn-client-script looks like this, btw.:

client
dev tun
proto udp
remote server-ip server-port
nobind 
resolv-retry infinite 
auth SHA512
cipher AES-256-CBC
keysize 256
comp-lzo
verb 2
mute-replay-warnings
ns-cert-type server
persist-key
persist-tun
key-direction 1
ca /path/to/file.crt
tls-auth /path/to/file.key 1
auth-user-pass /path/to/file
auth-nocache
script-security 2
up /etc/openvpn/update-resolv-conf
down /etc/openvpn/update-resolv-conf

---------------------------------------------

**EDIT** I hope I meet your request this time.

I just created the following setup:

  • one openvpn-server at computer A
  • one openvpn-client at my laptop B
  • created a vpn connection from my laptop B via umts to my computer A at home that allowed me to browse the web on my laptop B with the ip-address of computer A

I created my openvpn-server with the following script:

cat /etc/openvpn/server.conf 
port 11194
proto udp
dev tun10
tun-mtu 1500
mssfix 1450
ca /etc/openvpn/easy-rsa/keys/ca.crt
cert /etc/openvpn/easy-rsa/keys/ca.crt
key /etc/openvpn/easy-rsa/keys/ca.key
dh /etc/openvpn/easy-rsa/keys/dh2048.pem
server 10.9.0.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"
client-to-client
keepalive 5 60
comp-lzo
persist-key
persist-tun
#user openvpn
#group openvpn
status openvpn-SERVER-status.log
verb 6
cipher AES-256-CBC

The most important setting to achieve the dns-redirection thru your vpn should be: push "redirect-gateway def1 bypass-dhcp"

After that edit the following line in /etc/sysctl.conf

# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

and run sudo sysctl -p

Next create the iptables rules: While every policy was set to ACCEPT the following command was all I needed to execute: iptables -t nat -A POSTROUTING -o enp0s3 -j MASQUERADE

  • enp0s3 is the ethernet-card from computer A that is connected to the internet.

the vpn-client-script

The following script was used from the client laptop B to connect to the vpn-server at computer A

 
client
#tls-client
#key-direction 1
proto udp
port 11194
remote some.dyndns.org
dev tun
#persist-key
#persist-tun
#tun-mtu 1500
#mssfix 1450
#nobind 
#resolv-retry infinite 
keepalive 5 60
comp-lzo
cipher AES-256-CBC
ca /home/alex/Downloads/dellvpn/ca.crt
cert /home/alex/Downloads/dellvpn/dell-inspirion.crt
key /home/alex/Downloads/dellvpn/dell-inspirion.key
verb 2
script-security 2 
up /etc/openvpn/update-resolv-conf 
down /etc/openvpn/update-resolv-conf 

The most important lines to me are the last three lines. These prevent the dns-leak on linux systems. https://dnsleaktest.com/what-is-a-dns-leak.html

At this point I was able to browse with my laptop B with the IP of computer A.


**IPTABLES policy to DROP**

After I changed the defaul iptables policy to drop, things became to be complicated. Finally I successfully used the following script:

#!/bin/bash

##SCRIPT-SNIPPET taken from https://wiki.debianforum.de/Einfaches_Firewall-Script


IPTABLES="/sbin/iptables"

# Set Ports for Service
#------------------------------------------------------------------------------

pSSH="22"
pDNS="53"
pHTTP="80"
pHTTPS="443"
pOPENVPN="-p UDP --dport 11194"
pNTP="123"

# Set Networks
#------------------------------------------------------------------------------
LOCALNET="192.168.178.0/24"
VPNNET="10.9.0.0/24"


# Default policies.
#------------------------------------------------------------------------------

# Drop everything by default.
$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP
$IPTABLES -P OUTPUT DROP

# Set the nat/mangle/raw tables' chains to ACCEPT
$IPTABLES -t nat -P PREROUTING ACCEPT
$IPTABLES -t nat -P OUTPUT ACCEPT
$IPTABLES -t nat -P POSTROUTING ACCEPT

$IPTABLES -t mangle -P PREROUTING ACCEPT
$IPTABLES -t mangle -P INPUT ACCEPT
$IPTABLES -t mangle -P FORWARD ACCEPT
$IPTABLES -t mangle -P OUTPUT ACCEPT
$IPTABLES -t mangle -P POSTROUTING ACCEPT

# Cleanup.
#------------------------------------------------------------------------------

# Delete all
$IPTABLES -F
$IPTABLES -t nat -F
$IPTABLES -t mangle -F

# Delete all
$IPTABLES -X
$IPTABLES -t nat -X
$IPTABLES -t mangle -X

# Zero all packets and counters.
$IPTABLES -Z
$IPTABLES -t nat -Z
$IPTABLES -t mangle -Z


# Allow loopback interface to do anything.
$IPTABLES -A INPUT -i lo -j ACCEPT
$IPTABLES -A OUTPUT -o lo -j ACCEPT

# Allow incoming connections related to existing allowed connections.
$IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow outgoing connections EXCEPT invalid
$IPTABLES -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT


# Forward OpenVPN
#------------------------------------------------------------------------------
### Taken from the installscript at https://github.com/Nyr/openvpn-install/blob/master/openvpn-install.sh

IP=$(ip addr | grep 'inet' | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -o -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -1)
$IPTABLES -t nat -A POSTROUTING -s $VPNNET -j SNAT --to $IP
$IPTABLES -I FORWARD -s $VPNNET -j ACCEPT
$IPTABLES -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT


# Selectively allow certain outbound connections, block the rest.
#------------------------------------------------------------------------------

# Allow DNS. Few things will work without this.
$IPTABLES -A OUTPUT -m state --state NEW -p udp --dport $pDNS -j ACCEPT
$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport $pDNS -j ACCEPT


# Allow HTTP.
$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport $pHTTP -j ACCEPT

# Allow HTTPS.
$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport $pHTTPS -j ACCEPT

# Allow NTP.
$IPTABLES -A OUTPUT -m state --state NEW -p udp --dport $pNTP -j ACCEPT


# Selectively allow certain inbound connections, block the rest.
#------------------------------------------------------------------------------

# Allow inbound OPENVPN requests.
$IPTABLES -A INPUT -m state --state NEW $OPENVPN -j ACCEPT

# Allow inbound SSH request from specified IP-Range.
$IPTABLES -A INPUT -m state --state NEW -s $LOCALNET -p tcp --dport $pSSH -j ACCEPT
$IPTABLES -A INPUT -m state --state NEW -s $VPNNET -p tcp --dport $pSSH -j ACCEPT

# Exit gracefully.
#------------------------------------------------------------------------------

    exit 0

The most important routing lines should be:

# Forward OpenVPN
#------------------------------------------------------------------------------
### Taken from the installscript at https://github.com/Nyr/openvpn-install/blob/master/openvpn-install.sh

IP=$(ip addr | grep 'inet' | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -o -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -1)
$IPTABLES -t nat -A POSTROUTING -s $VPNNET -j SNAT --to $IP
$IPTABLES -I FORWARD -s $VPNNET -j ACCEPT
$IPTABLES -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

Make sure that $VPNNET is set to the appropriate IP in the openvpn-server.conf

As an alternative to the forwad rules above, I was also able to successfully create the tunnel and browse the web with these lines instead:

# Forward OpenVPN
#------------------------------------------------------------------------------

$IPTABLES -t nat -A POSTROUTING -o tun10 -j MASQUERADE
$IPTABLES -t nat -A POSTROUTING -o enp0s3 -j MASQUERADE
$IPTABLES -I FORWARD -o enp0s3 -i tun10 -j ACCEPT
$IPTABLES -I FORWARD -i enp0s3 -o tun10 -j ACCEPT
  • enp0s3 was the ethernet-card that was connected to the internet
  • tun10 was the ethernet-device created from my openvpn-server
3
  • I don't think this is a solution to my issue. I have a phone that is able to connect to the VPN via cellular data connection, however once the connection is established, it can no longer reach the internet.
    – rosstripi
    Jun 17, 2018 at 16:59
  • Just to make things clear. You want your clients to be able to log in from all over in the world (internet) at your vpn-server and from than on be able to browse the internet, with your vpn-server-ip-adress? Jun 18, 2018 at 4:47
  • I did just edit my answer. I hope if fits your needs now. Jun 19, 2018 at 0:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .