LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Distributions > Slackware
User Name
Password
Slackware This Forum is for the discussion of Slackware Linux.

Notices


Reply
  Search this Thread
Old 03-17-2018, 12:09 AM   #1
coralfang
Member
 
Registered: Nov 2010
Location: Bristol, UK
Distribution: Slackware, FreeBSD
Posts: 836
Blog Entries: 3

Rep: Reputation: 297Reputation: 297Reputation: 297
rc.firewall, how can i define vpn "killswitch" rules?


Hello, i am using AlienBOBS generated firewall ( http://www.slackware.com/~alien/efg/ ) as my rc.firewall script, i have been trying to add a "killswitch" rule so that all internet connections will be dropped unless they are going through my VPN on tun0.

I found the below rules in a web search, which allows the tun0 device to work (so the firewall doesn't block everything). However, this still allows me to disable the VPN/tun0 and then exposes my real address when using ping/curl. How can i alter this to work as a killswitch, so that when the VPN is inaccessible, no traffic is sent out to the internet?

I added this onto the end of the rc.firewall file;
Code:
# VPN rules

echo "Load rules for VPN on tun0"

# Allow the tcp connection on the openvpn port
$IPT -A INPUT -i $INET_IFACE -m state --state NEW -p udp --dport 1194 -j ACCEPT

# Allow TUN interface connections to OpenVPN server
$IPT -A INPUT -i tun+ -j ACCEPT

# Allow TUN interface connections to be forwarded through other interfaces
$IPT -A FORWARD -i tun+ -j ACCEPT
$IPT -A FORWARD -i tun+ -o $INET_IFACE -m state --state RELATED,ESTABLISHED -j ACCEPT
$IPT -A FORWARD -i $INET_IFACE -o tun+ -m state --state RELATED,ESTABLISHED -j ACCEPT

# NAT the VPN client traffic to the Internet. 
# change the ip address mask according to your info of tun0 result while running
# "ifconfig" command.
$IPT -t nat -A POSTROUTING -s 10.10.0.0/24 -o $INET_IFACE -j MASQUERADE

# If your default iptables OUTPUT value is not ACCEPT, you will also need a
# line like:
$IPT -A OUTPUT -o tun+ -j ACCEPT
I have tried various rules scattered across the web, but in all cases as soon as i drop/disconnect the VPN, my real IP address is exposed and can ping remote servers, so i'm not sure what else to try.
 
Old 03-17-2018, 05:35 AM   #2
abga
Senior Member
 
Registered: Jul 2017
Location: EU
Distribution: Slackware
Posts: 1,634

Rep: Reputation: 929Reputation: 929Reputation: 929Reputation: 929Reputation: 929Reputation: 929Reputation: 929Reputation: 929
Your actual network setup and the whole firewall script (mainly the default iptables policies) might be useful in order to properly understand your scenario . Sorry, no clue what rules set AlienBOB's script is generating, never used it.
It's important to specify what traffic you want to get through the VPN, local only / remote traffic only, or both. In case you're using this system as a gateway for your local LAN too, I just noticed you're using the FORWARD chain, that will complicate the setup a little, as you'll need to care about both local and remote traffic.

Redirecting only the local traffic through OpenVPN might be easier to achieve through the default gateway switch:
https://openvpn.net/index.php/open-s....html#redirect
A "killswitch" can be added in the form of some iptables rules to first allow the VPN initiation through the ethernet interface and then to drop all the rest of the outgoing traffic that does not go through the tun interface.

Last edited by abga; 03-18-2018 at 02:12 PM. Reason: misspelled AlienBOB :) sorry!
 
Old 03-17-2018, 10:20 AM   #3
coralfang
Member
 
Registered: Nov 2010
Location: Bristol, UK
Distribution: Slackware, FreeBSD
Posts: 836

Original Poster
Blog Entries: 3

Rep: Reputation: 297Reputation: 297Reputation: 297
Quote:
Originally Posted by abga View Post
Your actual network setup and the whole firewall script (mainly the default iptables policies) might be useful in order to properly understand your scenario . Sorry, no clue what rules set AlineBOB's script is generating, never used it.
It's important to specify what traffic you want to get through the VPN, local only / remote traffic only, or both. In case you're using this system as a gateway for your local LAN too, I just noticed you're using the FORWARD chain, that will complicate the setup a little, as you'll need to care about both local and remote traffic.

Redirecting only the local traffic through OpenVPN might be easier to achieve through the default gateway switch:
https://openvpn.net/index.php/open-s....html#redirect
A "killswitch" can be added in the form of some iptables rules to first allow the VPN initiation through the ethernet interface and then to drop all the rest of the outgoing traffic that does not go through the tun interface.

Well, this is what is generated (options to allow ssh inbound, and wlan0 as interface):
Code:
#!/bin/sh
#
# Generated iptables firewall script for the Linux 2.4 kernel and later.
# Script generated by Easy Firewall Generator for IPTables 1.15
# copyright 2002 Timothy Scott Morizot
# Modified for Slackware Linux by Eric Hameleers <alien@slackware.com>
# 
# This generator is adapted from the original to work on Slackware Linux.
# Basically, I corrected the path name to the iptables* commands
# and re-wrote this comment.
#
# It can be executed with the typical start and stop arguments.
# If used with stop, it will stop after flushing the firewall.
# The save and restore arguments will save or restore the rules
# from the /etc/sysconfig/iptables file.  The save and restore
# arguments are included to preserve compatibility with
# Redhat's or Fedora's init.d script if you prefer to use it.

# You may want to save this script as /etc/rc.d/rc.firewall
# and make it executable, like this:
#   chmod +x /etc/rc.d/rc.firewall
# Slackware Linux will then automatically run this script
# with the "start" parameter.

###############################################################################
# 
# Local Settings
#

# sysctl location.  If set, it will use sysctl to adjust the kernel parameters.
# If this is set to the empty string (or is unset), the use of sysctl
# is disabled.

SYSCTL="/sbin/sysctl -w" 

# To echo the value directly to the /proc file instead
# SYSCTL=""

# IPTables Location - adjust if needed

IPT="/usr/sbin/iptables"
IPTS="/usr/sbin/iptables-save"
IPTR="/usr/sbin/iptables-restore"

# Internet Interface
INET_IFACE="wlan0"

# Localhost Interface

LO_IFACE="lo"
LO_IP="127.0.0.1"

# Save and Restore arguments handled here
if [ "$1" = "save" ]
then
	echo -n "Saving firewall to /etc/sysconfig/iptables ... "
	$IPTS > /etc/sysconfig/iptables
	echo "done"
	exit 0
elif [ "$1" = "restore" ]
then
	echo -n "Restoring firewall from /etc/sysconfig/iptables ... "
	$IPTR < /etc/sysconfig/iptables
	echo "done"
	exit 0
fi

###############################################################################
#
# Load Modules
#

echo "Loading kernel modules ..."

# You should uncomment the line below and run it the first time just to
# ensure all kernel module dependencies are OK.  There is no need to run
# every time, however.

# /sbin/depmod -a

# Unless you have kernel module auto-loading disabled, you should not
# need to manually load each of these modules.  Other than ip_tables,
# ip_conntrack, and some of the optional modules, I've left these
# commented by default.  Uncomment if you have any problems or if
# you have disabled module autoload.  Note that some modules must
# be loaded by another kernel module.

# core netfilter module
/sbin/modprobe ip_tables

# the stateful connection tracking module
/sbin/modprobe ip_conntrack

# filter table module
# /sbin/modprobe iptable_filter

# mangle table module
# /sbin/modprobe iptable_mangle

# nat table module
# /sbin/modprobe iptable_nat

# LOG target module
# /sbin/modprobe ipt_LOG

# This is used to limit the number of packets per sec/min/hr
# /sbin/modprobe ipt_limit

# masquerade target module
# /sbin/modprobe ipt_MASQUERADE

# filter using owner as part of the match
# /sbin/modprobe ipt_owner

# REJECT target drops the packet and returns an ICMP response.
# The response is configurable.  By default, connection refused.
# /sbin/modprobe ipt_REJECT

# This target allows packets to be marked in the mangle table
# /sbin/modprobe ipt_mark

# This target affects the TCP MSS
# /sbin/modprobe ipt_tcpmss

# This match allows multiple ports instead of a single port or range
# /sbin/modprobe multiport

# This match checks against the TCP flags
# /sbin/modprobe ipt_state

# This match catches packets with invalid flags
# /sbin/modprobe ipt_unclean

# The ftp nat module is required for non-PASV ftp support
/sbin/modprobe ip_nat_ftp

# the module for full ftp connection tracking
/sbin/modprobe ip_conntrack_ftp

# the module for full irc connection tracking
/sbin/modprobe ip_conntrack_irc


###############################################################################
#
# Kernel Parameter Configuration
#
# See http://ipsysctl-tutorial.frozentux.net/chunkyhtml/index.html
# for a detailed tutorial on sysctl and the various settings
# available.

# Required to enable IPv4 forwarding.
# Redhat users can try setting FORWARD_IPV4 in /etc/sysconfig/network to true
# Alternatively, it can be set in /etc/sysctl.conf
#if [ "$SYSCTL" = "" ]
#then
#    echo "1" > /proc/sys/net/ipv4/ip_forward
#else
#    $SYSCTL net.ipv4.ip_forward="1"
#fi

# This enables dynamic address hacking.
# This may help if you have a dynamic IP address \(e.g. slip, ppp, dhcp\).
#if [ "$SYSCTL" = "" ]
#then
#    echo "1" > /proc/sys/net/ipv4/ip_dynaddr
#else
#    $SYSCTL net.ipv4.ip_dynaddr="1"
#fi

# This enables SYN flood protection.
# The SYN cookies activation allows your system to accept an unlimited
# number of TCP connections while still trying to give reasonable
# service during a denial of service attack.
if [ "$SYSCTL" = "" ]
then
    echo "1" > /proc/sys/net/ipv4/tcp_syncookies
else
    $SYSCTL net.ipv4.tcp_syncookies="1"
fi

# This enables source validation by reversed path according to RFC1812.
# In other words, did the response packet originate from the same interface
# through which the source packet was sent?  It's recommended for single-homed
# systems and routers on stub networks.  Since those are the configurations
# this firewall is designed to support, I turn it on by default.
# Turn it off if you use multiple NICs connected to the same network.
if [ "$SYSCTL" = "" ]
then
    echo "1" > /proc/sys/net/ipv4/conf/all/rp_filter
else
    $SYSCTL net.ipv4.conf.all.rp_filter="1"
fi

# This option allows a subnet to be firewalled with a single IP address.
# It's used to build a DMZ.  Since that's not a focus of this firewall
# script, it's not enabled by default, but is included for reference.
# See: http://www.sjdjweis.com/linux/proxyarp/ 
#if [ "$SYSCTL" = "" ]
#then
#    echo "1" > /proc/sys/net/ipv4/conf/all/proxy_arp
#else
#    $SYSCTL net.ipv4.conf.all.proxy_arp="1"
#fi

# The following kernel settings were suggested by Alex Weeks. Thanks!

# This kernel parameter instructs the kernel to ignore all ICMP
# echo requests sent to the broadcast address.  This prevents
# a number of smurfs and similar DoS nasty attacks.
if [ "$SYSCTL" = "" ]
then
    echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
else
    $SYSCTL net.ipv4.icmp_echo_ignore_broadcasts="1"
fi

# This option can be used to accept or refuse source routed
# packets.  It is usually on by default, but is generally
# considered a security risk.  This option turns it off.
if [ "$SYSCTL" = "" ]
then
    echo "0" > /proc/sys/net/ipv4/conf/all/accept_source_route
else
    $SYSCTL net.ipv4.conf.all.accept_source_route="0"
fi

# This option can disable ICMP redirects.  ICMP redirects
# are generally considered a security risk and shouldn't be
# needed by most systems using this generator.
#if [ "$SYSCTL" = "" ]
#then
#    echo "0" > /proc/sys/net/ipv4/conf/all/accept_redirects
#else
#    $SYSCTL net.ipv4.conf.all.accept_redirects="0"
#fi

# However, we'll ensure the secure_redirects option is on instead.
# This option accepts only from gateways in the default gateways list.
if [ "$SYSCTL" = "" ]
then
    echo "1" > /proc/sys/net/ipv4/conf/all/secure_redirects
else
    $SYSCTL net.ipv4.conf.all.secure_redirects="1"
fi

# This option logs packets from impossible addresses.
if [ "$SYSCTL" = "" ]
then
    echo "1" > /proc/sys/net/ipv4/conf/all/log_martians
else
    $SYSCTL net.ipv4.conf.all.log_martians="1"
fi


###############################################################################
#
# Flush Any Existing Rules or Chains
#

echo "Flushing Tables ..."

# Reset Default Policies
$IPT -P INPUT ACCEPT
$IPT -P FORWARD ACCEPT
$IPT -P OUTPUT ACCEPT
$IPT -t nat -P PREROUTING ACCEPT
$IPT -t nat -P POSTROUTING ACCEPT
$IPT -t nat -P OUTPUT ACCEPT
$IPT -t mangle -P PREROUTING ACCEPT
$IPT -t mangle -P OUTPUT ACCEPT

# Flush all rules
$IPT -F
$IPT -t nat -F
$IPT -t mangle -F

# Erase all non-default chains
$IPT -X
$IPT -t nat -X
$IPT -t mangle -X

if [ "$1" = "stop" ]
then
	echo "Firewall completely flushed!  Now running with no firewall."
	exit 0
fi

###############################################################################
#
# Rules Configuration
#

###############################################################################
#
# Filter Table
#
###############################################################################

# Set Policies

$IPT -P INPUT DROP
$IPT -P OUTPUT DROP
$IPT -P FORWARD DROP

###############################################################################
#
# User-Specified Chains
#
# Create user chains to reduce the number of rules each packet
# must traverse.

echo "Create and populate custom rule chains ..."

# Create a chain to filter INVALID packets

$IPT -N bad_packets

# Create another chain to filter bad tcp packets

$IPT -N bad_tcp_packets

# Create separate chains for icmp, tcp (incoming and outgoing),
# and incoming udp packets.

$IPT -N icmp_packets

# Used for UDP packets inbound from the Internet
$IPT -N udp_inbound

# Used to block outbound UDP services from internal network
# Default to allow all
$IPT -N udp_outbound

# Used to allow inbound services if desired
# Default fail except for established sessions
$IPT -N tcp_inbound

# Used to block outbound services from internal network
# Default to allow all
$IPT -N tcp_outbound

###############################################################################
#
# Populate User Chains
#

# bad_packets chain
#

# Drop INVALID packets immediately
$IPT -A bad_packets -p ALL -m conntrack --ctstate INVALID -j LOG \
    --log-prefix "Invalid packet: "

$IPT -A bad_packets -p ALL -m conntrack --ctstate INVALID -j DROP

# Then check the tcp packets for additional problems
$IPT -A bad_packets -p tcp -j bad_tcp_packets

# All good, so return
$IPT -A bad_packets -p ALL -j RETURN

# bad_tcp_packets chain
#
# All tcp packets will traverse this chain.
# Every new connection attempt should begin with
# a syn packet.  If it doesn't, it is likely a
# port scan.  This drops packets in state
# NEW that are not flagged as syn packets.


$IPT -A bad_tcp_packets -p tcp ! --syn -m conntrack --ctstate NEW -j LOG \
    --log-prefix "New not syn: "
$IPT -A bad_tcp_packets -p tcp ! --syn -m conntrack --ctstate NEW -j DROP

$IPT -A bad_tcp_packets -p tcp --tcp-flags ALL NONE -j LOG \
    --log-prefix "Stealth scan: "
$IPT -A bad_tcp_packets -p tcp --tcp-flags ALL NONE -j DROP

$IPT -A bad_tcp_packets -p tcp --tcp-flags ALL ALL -j LOG \
    --log-prefix "Stealth scan: "
$IPT -A bad_tcp_packets -p tcp --tcp-flags ALL ALL -j DROP

$IPT -A bad_tcp_packets -p tcp --tcp-flags ALL FIN,URG,PSH -j LOG \
    --log-prefix "Stealth scan: "
$IPT -A bad_tcp_packets -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP

$IPT -A bad_tcp_packets -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j LOG \
    --log-prefix "Stealth scan: "
$IPT -A bad_tcp_packets -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP

$IPT -A bad_tcp_packets -p tcp --tcp-flags SYN,RST SYN,RST -j LOG \
    --log-prefix "Stealth scan: "
$IPT -A bad_tcp_packets -p tcp --tcp-flags SYN,RST SYN,RST -j DROP

$IPT -A bad_tcp_packets -p tcp --tcp-flags SYN,FIN SYN,FIN -j LOG \
    --log-prefix "Stealth scan: "
$IPT -A bad_tcp_packets -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP

# All good, so return
$IPT -A bad_tcp_packets -p tcp -j RETURN

# icmp_packets chain
#
# This chain is for inbound (from the Internet) icmp packets only.
# Type 8 (Echo Request) is not accepted by default
# Enable it if you want remote hosts to be able to reach you.
# 11 (Time Exceeded) is the only one accepted
# that would not already be covered by the established
# connection rule.  Applied to INPUT on the external interface.
# 
# See: http://www.ee.siue.edu/~rwalden/networking/icmp.html
# for more info on ICMP types.
#
# Note that the stateful settings allow replies to ICMP packets.
# These rules allow new packets of the specified types.

# ICMP packets should fit in a Layer 2 frame, thus they should
# never be fragmented.  Fragmented ICMP packets are a typical sign
# of a denial of service attack.
$IPT -A icmp_packets --fragment -p ICMP -j LOG \
    --log-prefix "ICMP Fragment: "
$IPT -A icmp_packets --fragment -p ICMP -j DROP

# Echo - uncomment to allow your system to be pinged.
# Uncomment the LOG command if you also want to log PING attempts
# 
# $IPT -A icmp_packets -p ICMP -s 0/0 --icmp-type 8 -j LOG \
#    --log-prefix "Ping detected: "
# $IPT -A icmp_packets -p ICMP -s 0/0 --icmp-type 8 -j ACCEPT

# By default, however, drop pings without logging. Blaster
# and other worms have infected systems blasting pings.
# Comment the line below if you want pings logged, but it
# will likely fill your logs.
$IPT -A icmp_packets -p ICMP -s 0/0 --icmp-type 8 -j DROP

# Time Exceeded
$IPT -A icmp_packets -p ICMP -s 0/0 --icmp-type 11 -j ACCEPT

# Not matched, so return so it will be logged
$IPT -A icmp_packets -p ICMP -j RETURN

# TCP & UDP
# Identify ports at:
#    http://www.chebucto.ns.ca/~rakerman/port-table.html
#    http://www.iana.org/assignments/port-numbers

# udp_inbound chain
#
# This chain describes the inbound UDP packets it will accept.
# It's applied to INPUT on the external or Internet interface.
# Note that the stateful settings allow replies.
# These rules are for new requests.
# It drops netbios packets (windows) immediately without logging.

# Drop netbios calls
# Please note that these rules do not really change the way the firewall
# treats netbios connections.  Connections from the localhost and
# internal interface (if one exists) are accepted by default.
# Responses from the Internet to requests initiated by or through
# the firewall are also accepted by default.  To get here, the
# packets would have to be part of a new request received by the
# Internet interface.  You would have to manually add rules to
# accept these.  I added these rules because some network connections,
# such as those via cable modems, tend to be filled with noise from
# unprotected Windows machines.  These rules drop those packets
# quickly and without logging them.  This prevents them from traversing
# the whole chain and keeps the log from getting cluttered with
# chatter from Windows systems.
$IPT -A udp_inbound -p UDP -s 0/0 --destination-port 137 -j DROP
$IPT -A udp_inbound -p UDP -s 0/0 --destination-port 138 -j DROP

# Dynamic Address
# If DHCP, the initial request is a broadcast. The response
# doesn't exactly match the outbound packet.  This explicitly
# allow the DHCP ports to alleviate this problem.
# If you receive your dynamic address by a different means, you
# can probably comment this line.
$IPT -A udp_inbound -p UDP -s 0/0 --source-port 67 --destination-port 68 \
     -j ACCEPT


# Not matched, so return for logging
$IPT -A udp_inbound -p UDP -j RETURN

# udp_outbound chain
#
# This chain is used with a private network to prevent forwarding for
# UDP requests on specific protocols.  Applied to the FORWARD rule from
# the internal network.  Ends with an ACCEPT


# No match, so ACCEPT
$IPT -A udp_outbound -p UDP -s 0/0 -j ACCEPT

# tcp_inbound chain
#
# This chain is used to allow inbound connections to the
# system/gateway.  Use with care.  It defaults to none.
# It's applied on INPUT from the external or Internet interface.

# sshd
$IPT -A tcp_inbound -p TCP -s 0/0 --destination-port 22 -j ACCEPT


# Not matched, so return so it will be logged
$IPT -A tcp_inbound -p TCP -j RETURN

# tcp_outbound chain
#
# This chain is used with a private network to prevent forwarding for
# requests on specific protocols.  Applied to the FORWARD rule from
# the internal network.  Ends with an ACCEPT


# No match, so ACCEPT
$IPT -A tcp_outbound -p TCP -s 0/0 -j ACCEPT

###############################################################################
#
# INPUT Chain
#

echo "Process INPUT chain ..."

# Allow all on localhost interface
$IPT -A INPUT -p ALL -i $LO_IFACE -j ACCEPT

# Drop bad packets
$IPT -A INPUT -p ALL -j bad_packets

# DOCSIS compliant cable modems
# Some DOCSIS compliant cable modems send IGMP multicasts to find
# connected PCs.  The multicast packets have the destination address
# 224.0.0.1.  You can accept them.  If you choose to do so,
# Uncomment the rule to ACCEPT them and comment the rule to DROP
# them  The firewall will drop them here by default to avoid
# cluttering the log.  The firewall will drop all multicasts
# to the entire subnet (224.0.0.1) by default.  To only affect
# IGMP multicasts, change '-p ALL' to '-p 2'.  Of course,
# if they aren't accepted elsewhere, it will only ensure that
# multicasts on other protocols are logged.
# Drop them without logging.
$IPT -A INPUT -p ALL -d 224.0.0.1 -j DROP
# The rule to accept the packets.
# $IPT -A INPUT -p ALL -d 224.0.0.1 -j ACCEPT


# Inbound Internet Packet Rules

# Accept Established Connections
$IPT -A INPUT -p ALL -i $INET_IFACE -m conntrack --ctstate ESTABLISHED,RELATED \
     -j ACCEPT

# Route the rest to the appropriate user chain
$IPT -A INPUT -p TCP -i $INET_IFACE -j tcp_inbound
$IPT -A INPUT -p UDP -i $INET_IFACE -j udp_inbound
$IPT -A INPUT -p ICMP -i $INET_IFACE -j icmp_packets

# Drop without logging broadcasts that get this far.
# Cuts down on log clutter.
# Comment this line if testing new rules that impact
# broadcast protocols.
$IPT -A INPUT -m pkttype --pkt-type broadcast -j DROP

# Log packets that still don't match
$IPT -A INPUT -m limit --limit 3/minute --limit-burst 3 -j LOG \
    --log-prefix "INPUT packet died: "

###############################################################################
#
# FORWARD Chain
#

echo "Process FORWARD chain ..."

# Used if forwarding for a private network


###############################################################################
#
# OUTPUT Chain
#

echo "Process OUTPUT chain ..."

# Generally trust the firewall on output

# However, invalid icmp packets need to be dropped
# to prevent a possible exploit.
$IPT -A OUTPUT -p icmp -m conntrack --ctstate INVALID -j DROP

# Localhost
$IPT -A OUTPUT -p ALL -s $LO_IP -j ACCEPT
$IPT -A OUTPUT -p ALL -o $LO_IFACE -j ACCEPT

# To internet
$IPT -A OUTPUT -p ALL -o $INET_IFACE -j ACCEPT

# Log packets that still don't match
$IPT -A OUTPUT -m limit --limit 3/minute --limit-burst 3 -j LOG \
    --log-prefix "OUTPUT packet died: "

###############################################################################
#
# nat table
#
###############################################################################

# The nat table is where network address translation occurs if there
# is a private network.  If the gateway is connected to the Internet
# with a static IP, snat is used.  If the gateway has a dynamic address,
# masquerade must be used instead.  There is more overhead associated
# with masquerade, so snat is better when it can be used.
# The nat table has a builtin chain, PREROUTING, for dnat and redirects.
# Another, POSTROUTING, handles snat and masquerade.

echo "Load rules for nat table ..."

###############################################################################
#
# PREROUTING chain
#


###############################################################################
#
# POSTROUTING chain
#


###############################################################################
#
# mangle table
#
###############################################################################

# The mangle table is used to alter packets.  It can alter or mangle them in
# several ways.  For the purposes of this generator, we only use its ability
# to alter the TTL in packets.  However, it can be used to set netfilter
# mark values on specific packets.  Those marks could then be used in another
# table like filter, to limit activities associated with a specific host, for
# instance.  The TOS target can be used to set the Type of Service field in
# the IP header.  Note that the TTL target might not be included in the
# distribution on your system.  If it is not and you require it, you will
# have to add it.  That may require that you build from source.

echo "Load rules for mangle table ..."
Right at the bottom of that i placed the tun0 related rules from above (which allows the VPN to not be firewalled). It is just a workstation/desktop, and ideally what i need is to allow 192.168.0.0/24 for local lan connections (ssh access is needed locally on the lan), where any traffic that goes outside of the lan, should be forced through the VPN on tun0, however, if the VPN is disabled, then only the lan should be accessible. Admittedly, iptables is a bit over my head, so i did try ufw, however, that firewall doesn't seem to block traffic when the VPN is down.
 
Old 03-18-2018, 01:05 AM   #4
bassmadrigal
LQ Guru
 
Registered: Nov 2003
Location: West Jordan, UT, USA
Distribution: Slackware
Posts: 8,792

Rep: Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656
I know it doesn't give you exactly what you're looking for, but I set up something similar, however, mine was designed to only allow connections through the VPN with a particular user (in my case, the user was vpn). If the VPN was connected, that user could access the internet, but only through the VPN. If the VPN was disconnected, that user wouldn't have any internet access. I would then set up certain programs to be run by that user, which would ensure they would only operate when the VPN was connected.

The following is the rc.firewall rule I have that was able to set this up.

Code:
jbhansen@craven-moorhead:~$ cat /etc/rc.d/rc.firewall
#!/bin/bash

# Ensure any traffic from the vpn user is blocked by default
iptables -A OUTPUT ! -o lo -m owner --uid-owner vpn -j DROP
As well as the /etc/openvpn/iptables.sh script below (which is called in my openvpn script when the connection is created... I can provide that script if it would help):

Code:
#! /bin/bash
# Niftiest Software ? www.niftiestsoftware.com
# Modified version by HTPC Guides ? www.htpcguides.com

export INTERFACE="tun0"
export VPNUSER="vpn"
export LOCALIP="10.0.0.152"
export NETIF="eth0"

# flushes all the iptables rules, if you have other rules to use then add them into the script
iptables -F -t nat
iptables -F -t mangle
iptables -F -t filter

# mark packets from $VPNUSER
iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark
iptables -t mangle -A OUTPUT ! --dest $LOCALIP -m owner --uid-owner $VPNUSER -j MARK --set-mark 0x1
iptables -t mangle -A OUTPUT --dest $LOCALIP -p udp --dport 53 -m owner --uid-owner $VPNUSER -j MARK --set-mark 0x1
iptables -t mangle -A OUTPUT --dest $LOCALIP -p tcp --dport 53 -m owner --uid-owner $VPNUSER -j MARK --set-mark 0x1
iptables -t mangle -A OUTPUT ! --src $LOCALIP -j MARK --set-mark 0x1
iptables -t mangle -A OUTPUT -j CONNMARK --save-mark

# allow responses
iptables -A INPUT -i $INTERFACE -m conntrack --ctstate ESTABLISHED -j ACCEPT

# block everything incoming on $INTERFACE to prevent accidental exposing of ports
iptables -A INPUT -i $INTERFACE -j REJECT

# let $VPNUSER access lo and $INTERFACE
iptables -A OUTPUT -o lo -m owner --uid-owner $VPNUSER -j ACCEPT
iptables -A OUTPUT -o $INTERFACE -m owner --uid-owner $VPNUSER -j ACCEPT

# all packets on $INTERFACE needs to be masqueraded
iptables -t nat -A POSTROUTING -o $INTERFACE -j MASQUERADE

# reject connections from predator IP going over $NETIF
iptables -A OUTPUT ! --src $LOCALIP -o $NETIF -j REJECT

# Start routing script
/etc/openvpn/routing.sh

exit 0
And an /etc/openvpn/routing.sh script (called at the end of the iptables.sh script above):

Code:
#! /bin/bash
# Niftiest Software ? www.niftiestsoftware.com
# Modified version by HTPC Guides ? www.htpcguides.com

VPNIF="tun0"
VPNUSER="vpn"
GATEWAYIP=`ifconfig $VPNIF | egrep -o '([0-9]{1,3}\.){3}[0-9]{1,3}' | egrep -v '255|(127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})' | tail -n1`
if [[ `ip rule list | grep -c 0x1` == 0 ]]; then
ip rule add from all fwmark 0x1 lookup $VPNUSER
fi
ip route replace default via $GATEWAYIP table $VPNUSER
ip route append default via 127.0.0.1 dev lo table $VPNUSER
ip route flush cache

# run update-resolv-conf script to set VPN DNS
/etc/openvpn/update-resolv-conf

exit 0
And finally an /etc/sysctl.d/9999-vpn.conf

Code:
net.ipv4.conf.all.rp_filter = 2
net.ipv4.conf.default.rp_filter = 2
net.ipv4.conf.eth0.rp_filter = 2
I worked through this based on these guides... they're for Debian, but with enough tweaking, they still work with Slackware.

https://www.htpcguides.com/force-tor...-ubuntu-16-04/
https://www.htpcguides.com/configure...6-04-debian-8/
 
2 members found this post helpful.
Old 03-18-2018, 02:10 PM   #5
abga
Senior Member
 
Registered: Jul 2017
Location: EU
Distribution: Slackware
Posts: 1,634

Rep: Reputation: 929Reputation: 929Reputation: 929Reputation: 929Reputation: 929Reputation: 929Reputation: 929Reputation: 929
Following up from where I left before the night shift came in

@coralfang

If you find bassmadrigal's hint too complicated for your simple restrictive requirements, now that I have your entire actual firewall, I can develop on the simple default route switching solution that I previously proposed.
In order to only allow traffic through the VPN connection, once established and active, and drop anything else if this connection is not up, a "kill-switch" as you called it, you'll need to restrict all the default outgoing traffic first and then change the default route on your system to point to the route of your VPN connection.

1. Firewall related:
- the firewall that you got generated by using AlienBOB's script, post #3, is actually OK. The default policies I asked about are set on DROP:
Code:
# Set Policies

$IPT -P INPUT DROP
$IPT -P OUTPUT DROP
$IPT -P FORWARD DROP
- and there is a line that permits all outgoing traffic that you'll need to comment:
Code:
#$IPT -A OUTPUT -p ALL -o $INET_IFACE -j ACCEPT
- the VPN related rules that you added, from post #1, should be all removed and substituted with these:
EDIT> Forgot to keep the VPN traffic routed over ethernet/wlan0 - added a few lines (in bold).
inspiration:
https://serverfault.com/questions/34...ific-interface

Code:
#Allow  initial Name Resolution for resolving the public OpenVPN server IP. Necessary only if you don't already have an IP address for the public VPN server that's static
$IPT -A OUTPUT -o $INET_IFACE -p udp --dport 53 -j ACCEPT
$IPT -A INPUT -i $INET_IFACE -p udp --sport 53 -j ACCEPT

#Allow  the OpenVPN connection related traffic on ethernet/wlan
$IPT -A OUTPUT -o $INET_IFACE -p udp --dport 1194 -j ACCEPT
$IPT -A INPUT -i $INET_IFACE -p udp --sport 1194 -j ACCEPT

# Allow normal VPN traffic through the tun0 interface
$IPT -A OUTPUT -o tun0 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
$IPT -A INPUT -i tun0 -m state --state ESTABLISHED,RELATED -j ACCEPT

# Uncomment these if you want to allow the entire LAN related traffic, not only ssh (comment that ssh line from AlienBOB's script generated firewall if you use these)
#$IPT -A OUTPUT -o $INET_IFACE -d 192.168.0.0/24 -j ACCEPT
#$IPT -A INPUT -i $INET_IFACE -s 192.168.0.0/24 -j ACCEPT

#EDIT> Addendum - keeping the VPN traffic over ethernet/wlan0 instead of routing it through itself later on ...
#Substitute 192.168.0.1 with your actual LAN Gateway if different and 192.168.0.X with your local LAN IP
echo 2 > /proc/sys/net/ipv4/conf/eth0/rp_filter
#or, if going over wlan0
#echo 2 > /proc/sys/net/ipv4/conf/wlan0/rp_filter
/sbin/ip rule add fwmark 1194 table 10
/sbin/ip route add default via 192.168.0.1 table 10
/sbin/ip route flush cache
$IPT -t mangle -A OUTPUT -p udp --dport 1194 -j MARK --set-mark 1194
$IPT -t nat -A POSTROUTING -o $INET_IFACE -j SNAT --to-source 192.168.0.X
- and that's pretty much it related to firewalling.

2. Routing & DNS related:
- here, without knowing anything about your VPN connection setup, I'll go through some guesswork and propose some alternatives.
- in order to allow the local traffic on 192.168.0.0/24 going through ethernet/wlan and only route the rest of the traffic through the VPN, you'll need to change your actual LAN Gateway default route 192.168.0.1 (guessing) into the one that you receive/is set on the VPN
- If you change your default gateway from within openvpn (your openvpn server is configured to push the default route - server side: push "redirect-gateway def1" & client side: redirect-gateway def1), then you're just fine. Maybe your openvpn server is also configured to push a DNS resolver and then everything is just wonderful, no need to worry about anything else, your setup is complete.


If none of the above VPN related configurations are true, then you'll need to help yourself with some simple scripting.

The Easy Way - create a script in the form of a rc.vpn and start/stop your vpn:
Code:
#....
#start VPN - substitute VPN_GATEWAY & VPN_DNS with the actual addresses
/usr/sbin/openvpn /etc/openvpn.conf
/sbin/ip route del default
/sbin/ip route add default via VPN_GATEWAY
echo "nameserver VPN_DNS" > /etc/resolv.conf
#....
#stop VPN - substitute 192.168.0.1 with your actual LAN GATEWAY / DNS
/bin/killall openvpn
/sbin/ip route del default
/sbin/ip route add default via 192.168.0.1
echo "nameserver 192.168.0.1" > /etc/resolv.conf
The Complicated Way - create 2 executable (chmod +x) scripts in /etc/openvpn/ and call them from withing the openvpn.conf file with the up/down directives. Note that you'll need to run openvpn as root and not use the user/group options in openvpn.conf. There is a well known issue with openvpn in that it will fail to execute (no root rights from within the chroot) the down script and only successfully execute the up one, even if it was launched as root.
- content of /etc/openvpn/up.sh
Code:
#!  /bin/sh
#substitute VPN_GATEWAY & VPN_DNS with the actual addresses
/sbin/ip route del default
/sbin/ip route add default via VPN_GATEWAY
echo "nameserver VPN_DNS" > /etc/resolv.conf
- content of /etc/openvpn/down.sh
Code:
#!  /bin/sh
#substitute 192.168.0.1 with your actual LAN GATEWAY / DNS
/sbin/ip route del default
/sbin/ip route add default via 192.168.0.1
echo "nameserver 192.168.0.1" > /etc/resolv.conf
- add these lines to your openvpn.conf file:
Code:
script-security 2
up '/etc/openvpn/up.sh'
down '/etc/openvpn/down.sh'
The Even More Complicated Way - the same as above but if you insist running openvpn as the openvpn user/group, then you'll need to allow openvpn to use the shell, add openvpn to sudoers and change the rights of the /etc/resolv.conf
- allow the openvpn user to use the shell - edit /etc/passwd and make sure that the openvpn user has /bin/bash instead of /bin/false
- add the openvpn user to the sudoers in order to execute the ip command as root, run visudo and add the following line:
Code:
openvpn ALL=(ALL) NOPASSWD:/sbin/ip
- change the rights on /etc/resolv.conf - run:
Code:
chown openvpn:openvpn /etc/resolv.conf
- change the /etc/openvpn/down.sh script and use sudo:
Code:
#!  /bin/sh
#substitute 192.168.0.1 with your actual LAN GATEWAY / DNS
/usr/bin/sudo /sbin/ip route del default
/usr/bin/sudo /sbin/ip route add default via 192.168.0.1
echo "nameserver 192.168.0.1" > /etc/resolv.conf

Last edited by abga; 03-18-2018 at 06:37 PM. Reason: typo: $IPT -A INPUT -i tun0 instead of -s tun0 & forgot to keep the vpn traffic on eth0/wlan0
 
1 members found this post helpful.
Old 03-18-2018, 04:17 PM   #6
abga
Senior Member
 
Registered: Jul 2017
Location: EU
Distribution: Slackware
Posts: 1,634

Rep: Reputation: 929Reputation: 929Reputation: 929Reputation: 929Reputation: 929Reputation: 929Reputation: 929Reputation: 929
Just noticed a glitch in my previous post, related to AlienBOB's script generated firewall. I've instructed you to drop all outgoing packets by commenting out:
Code:
#$IPT -A OUTPUT -p ALL -o $INET_IFACE -j ACCEPT
But then you'll need to address the sshd tcp outgoing traffic on port 22 if you still keep that line and don't consider to ditch it and open up for the whole LAN traffic.
Code:
# Uncomment these if you want to allow the entire LAN related traffic, not only ssh (comment that ssh line from AlienBOB's script generated firewall if you use these)
#$IPT -A OUTPUT -o $INET_IFACE -d 192.168.0.0/24 -j ACCEPT
#$IPT -A INPUT -i $INET_IFACE -s 192.168.0.0/24 -j ACCEPT
Your existent rule to let incoming ssh tcp connection on port 22:
Code:
# sshd
$IPT -A tcp_inbound -p TCP -s 0/0 --destination-port 22 -j ACCEPT
needs this additional line in order to let the sshd generated traffic go out too:
Code:
$IPT -A OUTPUT -o $INET_IFACE -p tcp -d 0/0 --sport 22 -j ACCEPT
 
1 members found this post helpful.
Old 03-19-2018, 07:30 PM   #7
slacktroll
Member
 
Registered: May 2011
Distribution: Slackware64/current
Posts: 175

Rep: Reputation: 44
Nice for all the help here!

From my experience, It's really easier to just remove the default gateway and add routes only to the vpn provider ip address and add a default route through the tun or tap device through it's gateway...
And if the vpn goes down, no need for kill switch, because nothing will route at all.

It might be a bit annoying when using dhcpcd which overwrites /etc/resolv.conf, adds routes etc. but it's possible!
 
1 members found this post helpful.
Old 03-22-2018, 03:54 PM   #8
coralfang
Member
 
Registered: Nov 2010
Location: Bristol, UK
Distribution: Slackware, FreeBSD
Posts: 836

Original Poster
Blog Entries: 3

Rep: Reputation: 297Reputation: 297Reputation: 297
Thanks abga/bassmadrigal, that's really helpful cheers. Since i last posted i gave up with iptables as it was a bit over my head figuring out. I ended up installing ufw and made an rc.ufw script to set some rules, which has been working.

Although i'd much prefer to use killswitch along with the other settings within the previous firewall script, so i'll definitely take a look at what you posted. Many thanks for that!

In case anyone else might find this through a search, you cna create a vpn killswitch for ufw with this rc script:
Code:
#!/bin/sh

#network interface
IFACE=wlan0
#vpn interface
IFACE_TUN=tun0
#remote port to connect vpn (check *.ovpn files to find this)
REMOTE_VPN_PORT=1195
#port for DNS requests
DNS_PORT=53

ufw_start() {
	ufw --force reset

	#block all traffic by default
	ufw default deny incoming 
	ufw default deny outgoing

	#allow traffic on tun device
	ufw allow out on ${IFACE_TUN}

	#allow DNS/OpenVPN connections on network interface
	ufw allow out on $IFACE to any port ${DNS_PORT},${REMOTE_VPN_PORT} proto udp

	#the address range for ${IFACE_TUN}
	ufw allow out to 10.10.0.0/24

	#allow LAN activity
	ufw allow out to 192.168.0.0/24

	#enable the firewall
	ufw enable
}

ufw_stop() {
	ufw disable
}

case "$1" in
    start)
        ufw_start
    ;;
    restart)
	ufw_stop
        ufw_start
    ;;
    stop)
        ufw_stop
    ;;
    *)
    echo "Usage: $0 (start|stop|restart)"
esac

Last edited by coralfang; 03-22-2018 at 03:57 PM.
 
1 members found this post helpful.
Old 03-23-2018, 05:53 PM   #9
abga
Senior Member
 
Registered: Jul 2017
Location: EU
Distribution: Slackware
Posts: 1,634

Rep: Reputation: 929Reputation: 929Reputation: 929Reputation: 929Reputation: 929Reputation: 929Reputation: 929Reputation: 929
Well, I've also learned something new out of your last post!
Never heard of ufw before:
https://en.wikipedia.org/wiki/Uncomplicated_Firewall
Thing is, regardless of what abstraction layer you try to put over netfilter (iptables), you cannot "uncomplicate" the networking&firewalling itself. You'll loose both the transparency over the details of the firewall rules and the usage flexibility of these rules.

Starting with the firewall that you got from using AlienBOB's script was not the optimal approach given that you're not that much experienced with iptables. I did respect your decision and the hard work AlineBOB put in that general & all covering & quite complex firewall, nevertheless is what Slackware (community) helps you with. For a more simplistic "beginner level" approach, you can use some bits from AlineBOB's firewall, what bassmadrigal suggested & the rules I wrote:
Code:
#1. first you need to flush all rules - bassmadrigal's section:
# flushes all the iptables rules, if you have other rules to use then add them into the script
/usr/sbin/iptables -F -t nat
/usr/sbin/iptables -F -t mangle
/usr/sbin/iptables -F -t filter
#2. then you'll need to define the policies - AlienBOB's section: 
# Set Policies
/usr/sbin/iptables -P INPUT DROP
/usr/sbin/iptables -P OUTPUT DROP
/usr/sbin/iptables -P FORWARD DROP
#3. The rules I wrote for restricting the traffic that doesn't go out over the vpn - your original question - killswitch
#Allow  initial Name Resolution for resolving the public OpenVPN server IP. Necessary only if you don't already have an IP address for the public VPN server that's static - substitute the $INET_IFACE with either eth0 or wlan0 - depending which interface you're using
/usr/sbin/iptables -A OUTPUT -o $INET_IFACE -p udp --dport 53 -j ACCEPT
/usr/sbin/iptables -A INPUT -i $INET_IFACE -p udp --sport 53 -j ACCEPT

#Allow  the OpenVPN connection related traffic on ethernet/wlan
/usr/sbin/iptables -A OUTPUT -o $INET_IFACE -p udp --dport 1194 -j ACCEPT
/usr/sbin/iptables -A INPUT -i $INET_IFACE -p udp --sport 1194 -j ACCEPT

# Allow normal VPN traffic through the tun0 interface
/usr/sbin/iptables -A OUTPUT -o tun0 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
/usr/sbin/iptables -A INPUT -i tun0 -m state --state ESTABLISHED,RELATED -j ACCEPT

# (Uncomment) Use these if you want to allow the entire LAN related traffic, not only ssh
/usr/sbin/iptables -A OUTPUT -o $INET_IFACE -d 192.168.0.0/24 -j ACCEPT
/usr/sbin/iptables -A INPUT -i $INET_IFACE -s 192.168.0.0/24 -j ACCEPT
And there you have it in pure iptables rules without the use of ufw. I was not sure if your vpn was configured to change the default route and that's why I covered this with those extra ip instructions, making the setup a little more complicated. Worth to mention that unless you're scripting addicted (script kiddie) or you have more than 2-3 interfaces on your system, try to stay away from scripting the firewall, as it will get you confused, especially if you're a beginner. Define clear sections, copy-paste the rules and keep your firewall short - design it on a restrictive policy first and on a lowest possible effort second, creating too many rules & chains, pushing the packets through these rules& chains will delay them and create an overhead on your system, especially for slower processors & on XGigabit adapters. Don't log anything else than what you're dropping on the services you're listening, it's useless, especially now when portscans are a de facto phenomenon on the Internet. Well, respecting the KISS principle is also very important in firewalling

On your ufw script I can observe a little redundancy - maybe a really weird way ufw is creating rules:

- this rule has a broad coverage, accepting all the traffic (all the destinations) over the IFACE_TUN interface:
Code:
	#allow traffic on tun device
	ufw allow out on ${IFACE_TUN}
And then it is followed by a stricter rule for the 10.10.0.0/24 network, traffic that was already covered in the previous rule and that will also go out on every other interface (depending on the default route you have defined):
Code:
	#the address range for ${IFACE_TUN}
	ufw allow out to 10.10.0.0/24
This kind of rules definition is a little confusing and that's why I strongly encourage you to lecture/learn about iptables and iproute2, these are the standard tools under Linux that you'll need for controlling the traffic on your host/network. As mentioned before, there is no other easier way, but maybe a more confusing one.

A nice iptables tutorial:
https://www.frozentux.net/iptables-t...tml/index.html
together with the best schematic I could find ATM:
https://upload.wikimedia.org/wikiped...acket-flow.svg

And on iproute2, check the documentation section (bottom) from this link:
https://wiki.linuxfoundation.org/networking/iproute2

Last edited by abga; 03-23-2018 at 05:55 PM. Reason: typo ... obviously
 
  


Reply

Tags
iptables, killswitch, openvpn, vpn


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Constant stream of "IPv4: martian source" and "FIREWALL:INPUT" after plugging eth0 in anon03 Linux - Networking 1 08-07-2015 07:38 AM
Setting up VPN and IPTable rules to protect a HTPC "Always On" Media Downloader legendscoach Linux - Security 5 06-29-2015 09:06 AM
How does one define "-j LOG" targets in the firewall rules? tonj Linux - Security 2 07-06-2012 12:28 AM
[SOLVED] "Wireless is disabled" even with killswitch off greatquizzard Linux - Wireless Networking 14 10-17-2010 05:32 AM
How to edit "/etc/udev/rules.d/40-basic-permissions.rules" file cygan Linux - Newbie 11 03-09-2009 05:22 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Distributions > Slackware

All times are GMT -5. The time now is 08:11 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration