Linux - SecurityThis forum is for all security related questions.
Questions, tips, system compromises, firewalls, etc. are all included here.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I've created my first iptables firewall from my research and a parts of other scripts on the net.
I'd like some to ask if you could review it's effectiveness. Anything that needs to be added, removed or moved?
Below is the full script (/etc/rc.d/rc.firewall) and at the very end is the status output.
Thank you.
Code:
#!/bin/sh
# Local Area Network configuration.
#
# your LAN's IP range and localhost IP. /24 means to only use the first 24
# bits of the 32 bit IP adress. the same as netmask 255.255.255.0
LAN_IP="10.168.2.2"
LAN_IP_RANGE="10.168.2.0/24"
LAN_BCAST_ADRESS="10.168.2.255"
LAN_IFACE="wlan0"
# Localhost Configuration.
LO_IFACE="lo"
LO_IP="127.0.0.1"
# Internet Configuration.
INET_IP="x.x.x.x"
INET_IFACE="wlan0"
# IPTables Configuration.
IPT="/usr/sbin/iptables"
MODULE="ip_tables iptable_nat iptable_mangle iptable_filter ipt_state ipt_LOG ip_conntrack nfnetlink_queue nfnetlink ipt_NFQUEUE"
IPFORWARD="0"
TCP_IN=""
TCP_OUT="ftp http https 1863 mmcc aol"
UDP_IN=""
UDP_OUT=""
# MoBlock Configuration
ACTIVATE_CHAINS=1
WHITE_TCP_IN=""
WHITE_UDP_IN=""
WHITE_TCP_OUT="http https"
WHITE_UDP_OUT=""
WHITE_TCP_FW=""
WHITE_UDP_FW=""
############################################################################
# Start Firewall
start_firewall() {
# Load modules
for modules in $MODULE ; do
modprobe $modules #2> /dev/null
echo "Firewall: loading module [ OK ] $modules"
done
echo "Firewall: Optimal policy | LOADED."
# Disable TCP timestamps to reduce TCP stack workload:
echo "0" > /proc/sys/net/ipv4/tcp_timestamps
# Enable TCP SYN Cookie Protection:
if [ -e /proc/sys/net/ipv4/tcp_syncookies ]; then
echo "1" > /proc/sys/net/ipv4/tcp_syncookies
fi
# Enable reverse path filtering for anti-spoofing:
echo "1" > in /proc/sys/net/ipv4/conf/all/rp_filter
# Allow redirects from trusted gateways only:
echo "1" > /proc/sys/net/ipv4/conf/all/secure_redirects
# Do not send Redirect Messages:
echo "0" > /proc/sys/net/ipv4/conf/all/send_redirects
# Disable ICMP Redirect Acceptance:
echo "0" > /proc/sys/net/ipv4/conf/all/accept_redirects
# Disable source routed packets as they are ridiculous:
echo "0" > /proc/sys/net/ipv4/conf/all/accept_source_route
# Ignore PINGs which have been BROADCAST (broadcast echo protection):
echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
# Enable bad error message protection
echo "1" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
# Enable or disable IP forwarding
echo "$IPFORWARD" > /proc/sys/net/ipv4/ip_forward
if [ `cat /proc/sys/net/ipv4/ip_forward` -eq 0 ]; then
echo "Firewall: IP forwarding disabled."
else
echo "Firewall: IP forwarding enabled."
fi;
# Log spoofed packets, source-routed packets, and redirect packets
echo "1" > /proc/sys/net/ipv4/conf/all/log_martians
# Default Policies for no match
$IPT -P INPUT DROP
$IPT -P OUTPUT ACCEPT
$IPT -P FORWARD DROP
# Create a chain to filter INVALID packets
$IPT -N BAD_PKTS
# Create another chain to filter bad tcp packets
$IPT -N BAD_TCPPKTS
# Create separate chains for ICMP
$IPT -N ICMP_PKTS
# Create MoBlock Chains
$IPT -N MOBLOCK_IN
$IPT -N MOBLOCK_OUT
$IPT -N MOBLOCK_FW
#### BAD_PKTS chain ################
# Drop INVALID packets immediately
$IPT -A BAD_PKTS -p ALL -m state --state INVALID -j LOG --log-prefix "fp=BAD_PKTS:1 a=DROP "
$IPT -A BAD_PKTS -p ALL -m state --state INVALID -j DROP
# Then check the tcp packets for additional problems
$IPT -A BAD_PKTS -p tcp -j BAD_TCPPKTS
# All good, so return
$IPT -A BAD_PKTS -p ALL -j RETURN
#### BAD_TCPPKTS chain #############
# All tcp pkts will traverse this chain. Every new connection attempt should begin with a syn packet.
# If not, it's likely a port scan. This drops pkts in state NEW that are not flagged as syn pkts.
$IPT -A BAD_TCPPKTS -p tcp ! --syn -m state --state NEW -j LOG --log-prefix "fp=BAD_TCPPKTS:1 a=DROP "
$IPT -A BAD_TCPPKTS -p tcp ! --syn -m state --state NEW -j DROP
$IPT -A BAD_TCPPKTS -p tcp --tcp-flags ALL NONE -j LOG --log-prefix "fp=BAD_TCPPKTS:2 a=DROP "
$IPT -A BAD_TCPPKTS -p tcp --tcp-flags ALL NONE -j DROP
$IPT -A BAD_TCPPKTS -p tcp --tcp-flags ALL ALL -j LOG --log-prefix "fp=BAD_TCPPKTS:3 a=DROP "
$IPT -A BAD_TCPPKTS -p tcp --tcp-flags ALL ALL -j DROP
$IPT -A BAD_TCPPKTS -p tcp --tcp-flags ALL FIN,URG,PSH -j LOG --log-prefix "fp=BAD_TCPPKTS:4 a=DROP "
$IPT -A BAD_TCPPKTS -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
$IPT -A BAD_TCPPKTS -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j LOG --log-prefix "fp=BAD_TCPPKTS:5 a=DROP "
$IPT -A BAD_TCPPKTS -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
$IPT -A BAD_TCPPKTS -p tcp --tcp-flags SYN,RST SYN,RST -j LOG --log-prefix "fp=BAD_TCPPKTS:6 a=DROP "
$IPT -A BAD_TCPPKTS -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
$IPT -A BAD_TCPPKTS -p tcp --tcp-flags SYN,FIN SYN,FIN -j LOG --log-prefix "fp=BAD_TCPPKTS:7 a=DROP "
$IPT -A BAD_TCPPKTS -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
# All good, so return
$IPT -A BAD_TCPPKTS -p tcp -j RETURN
#### ICMP_PKTS 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.
# N.B. that 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_PKTS --fragment -p ICMP -j LOG --log-prefix "fp=ICMP_PKTS:1 a=DROP "
$IPT -A ICMP_PKTS --fragment -p ICMP -j DROP
# Echo - uncomment to allow your system to be pinged. Uncomment LOG command if you want to log attempts
# $IPT -A ICMP_PKTS -p ICMP -s 0/0 --icmp-type 8 -j LOG --log-prefix "fp=ICMP_PKTS:2 a=ACCEPT "
# $IPT -A ICMP_PKTS -p ICMP -s 0/0 --icmp-type 8 -j ACCEPT
# By default, drop pings without logging. Blaster & 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_PKTS -p ICMP -s 0/0 --icmp-type 8 -j DROP
# Time Exceeded
$IPT -A ICMP_PKTS -p ICMP -s 0/0 --icmp-type 11 -j ACCEPT
# Not matched, so return so it will be logged
$IPT -A ICMP_PKTS -p ICMP -j RETURN
#### MOBLOCK chains #################
# MOBLOCK_IN chain rule: Incoming traffic queued
$IPT -I MOBLOCK_IN -p all -j NFQUEUE
# MOBLOCK_OUT chain rule: Outgoing traffic queued
$IPT -I MOBLOCK_OUT -p all -j NFQUEUE
# MOBLOCK_FW chain rule: Forwarded traffic queued
$IPT -I MOBLOCK_FW -p all -j NFQUEUE
# MoBlock Bypass
for PORT in $WHITE_TCP_OUT; do
$IPT -I MOBLOCK_OUT -p tcp --dport $PORT -j ACCEPT
done
for PORT in $WHITE_UDP_OUT; do
$IPT -I MOBLOCK_OUT -p udp --dport $PORT -j ACCEPT
done
for PORT in $WHITE_TCP_IN; do
$IPT -I MOBLOCK_IN -p tcp --dport $PORT -j ACCEPT
done
for PORT in $WHITE_UDP_IN; do
$IPT -I MOBLOCK_IN -p udp --dport $PORT -j ACCEPT
done
for PORT in $WHITE_TCP_FW; do
$IPT -I MOBLOCK_FW -p tcp --dport $PORT -j ACCEPT
done
for PORT in $WHITE_UDP_FW; do
$IPT -I MOBLOCK_FW -p udp --dport $PORT -j ACCEPT
done
# Start MoBlock, Load list and start logging
/ul/NIProgs/MoBlock/moblock_control start
#### INPUT chain ####################
# Drop bad packets
$IPT -I INPUT 1 -p ALL -j BAD_PKTS
# Allow loopback traffic
$IPT -A INPUT -p all -i $LO_IFACE -j ACCEPT
# If MoBlock activated then state NEW packets directed to MobBlock (accepted or dropped)
if [ $ACTIVATE_CHAINS -eq 1 ]; then
$IPT -A INPUT -i $LAN_IFACE -p tcp -m state --state NEW --tcp-flags SYN,RST,ACK SYN --dport 37766:37768 -j MOBLOCK_IN
$IPT -A INPUT -i $LAN_IFACE -p udp -m state --state NEW --dport 37766:37768 -j MOBLOCK_IN
fi;
# Accept existing connections
$IPT -A INPUT -i $LAN_IFACE -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
## Allow TCP IN traffic based on port number
for PORT in $TCP_IN; do
$IPT -A INPUT -i $LAN_IFACE -p tcp --dport $PORT -j ACCEPT
done
## Allow UDP IN traffic based on port number
for PORT in $UDP_IN; do
$IPT -A INPUT -i $LAN_IFACE -p udp --dport $PORT -j ACCEPT
done
$IPT -A INPUT -p ICMP -i $INET_IFACE -j ICMP_PKTS
# 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 -j LOG --log-prefix "fp=INPUT:99 a=DROP "
#### OUTPUT chain ###################
# However, invalid icmp packets need to be dropped
# to prevent a possible exploit.
$IPT -A OUTPUT -m state -p icmp --state INVALID -j DROP
# Allow loopback traffic
$IPT -A OUTPUT -p ALL -s $LO_IP -j ACCEPT
$IPT -A OUTPUT -p all -o $LO_IFACE -j ACCEPT
# If MoBlock activated then state NEW packets directed to MoBlock (accepted or dropped)
if [ $ACTIVATE_CHAINS -eq 1 ]; then
$IPT -I OUTPUT -o $LAN_IFACE -p udp -m state --state NEW --sport 37766:37768 -j MOBLOCK_OUT
$IPT -I OUTPUT -o $LAN_IFACE -p tcp -m state --state NEW --dport 80 -j MOBLOCK_OUT
fi;
# Accept existing connections
$IPT -A OUTPUT -o $LAN_IFACE -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow Receive DNS ()
$IPT -A OUTPUT -o $LAN_IFACE -m state --state NEW,ESTABLISHED,RELATED -p udp --dport 53 -j ACCEPT
$IPT -A OUTPUT -o $LAN_IFACE -m state --state NEW,ESTABLISHED,RELATED -p tcp --dport 53 -j ACCEPT
## Allow TCP OUT traffic based on port number
for PORT in $TCP_OUT; do
$IPT -A OUTPUT -o $LAN_IFACE -p tcp --dport $PORT -j ACCEPT
done
## Allow UDP OUT traffic based on port number
for PORT in $UDP_OUT; do
$IPT -A OUTPUT -o $LAN_IFACE -p udp --dport $PORT -j ACCEPT
done
# Log packets that still don't match
$IPT -A OUTPUT -j LOG --log-prefix "fp=OUTPUT:99 a=DROP "
#### FORWARD chain ##################
# Accept existing connections
$IPT -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
}
# Local Traffic only
local_only() {
echo "Firewall: Allowing local traffic"
$IPT -A INPUT -p all -i lo -j ACCEPT
$IPT -A OUTPUT -p all -o lo -j ACCEPT
}
# Block ALL
block_all() {
echo "Firewall: Block all | LOADED"
$IPT -P INPUT DROP
$IPT -P OUTPUT DROP
$IPT -P FORWARD DROP
}
# Stop Firewall
stop_firewall() {
echo "Firewall: Resetting default policy"
$IPT -P INPUT ACCEPT
$IPT -P OUTPUT ACCEPT
$IPT -P FORWARD ACCEPT
echo "Firewall: Stopped"
}
# Flushing, removing and zeroing tables
reset_firewall() {
echo "Firewall: Resetting tables & chains"
CHAINS=`cat /proc/net/ip_tables_names`
for i in $CHAINS; do
$IPT -t $i -F
$IPT -t $i -X
$IPT -t $i -Z
done
}
# Firewall Status
status_firewall () {
$IPT -L -n -v --line-numbers
}
# EXECUTE
case "$1" in
start|restart|reload)
reset_firewall
start_firewall
;;
stop)
reset_firewall
stop_firewall
;;
local)
reset_firewall
block_all
local_only
;;
block)
reset_firewall
block_all
;;
status)
status_firewall
;;
*)
echo "Usage: $0 {start|stop|restart|reload|local|block|status}";
exit 1
;;
esac
Is there some particular reason why you've chosen to start off with such a difficult to read (and quite likely overly-complicated) iptables script? I began reading your script but quit after a while for fear my head would explode.
My guess is that other members have had similar experiences, which would explain why you haven't gotten any feedback on it yet. I'd like to understand what you are trying to accomplish with your script (that's the first thing to ask yourself when making one). Also, I would like to ask if you understand every single line in your script.
Difficult to read how? As in the formatting or because I've used a lot of variables for each command? It may look confusing because I'm reusing a lot of the code. Yes I do understand every single line. I'll explain a little.
I decided to use many variables because I travel a lot with the laptop. For instance, if I'm using Ethernet instead of wireless I can just replace that particular variable (wlan0) with eth0, or I can change my settings based on what network I'm connected to. Other examples: modules are loaded depending if they are listed in a variable. I use the for loop to load the modules and echo that they have loaded (done in 5 lines instead of 20). I did the same with port numbers, If I need to use SSH I can just add "22" to the variable and I'm done.
Just makes it easier, more adaptable and saves a lot of typing. I also use MoBlock so might make it seem more complex.
- The script begins with enabling/disabling a few options.
- Setting the default policies.
- Creating my chains
- INPUT, OUTPUT direct packets to specified chains
- I call another script to start MoBlock
- state NEW packets on port X are sent to the MoBlock chains (if enabled)
- I can redirect certain packets to MoBlock or bypass it (if enabled)
- TCP packets are checked for validity and dealt with
- ICMP packets are handled depending on type
The rest of the script is your usual restarting, stopping, etc. I also added the ability to block all traffic or only allow local traffic. It all works fine but I just wanted that second opinion.
Difficult to read how? As in the formatting or because I've used a lot of variables for each command?
I guess a bit of both actually. In any case, it's just a matter of personal preference.
For example, let's take 30 lines from your script:
Code:
# Disable TCP timestamps to reduce TCP stack workload:
echo "0" > /proc/sys/net/ipv4/tcp_timestamps
# Enable TCP SYN Cookie Protection:
if [ -e /proc/sys/net/ipv4/tcp_syncookies ]; then
echo "1" > /proc/sys/net/ipv4/tcp_syncookies
fi
# Enable reverse path filtering for anti-spoofing:
for f in /proc/sys/net/ipv4/conf/*/rp_filter ; do
echo "1" > $f
done
# Allow redirects from trusted gateways only:
echo "1" > /proc/sys/net/ipv4/conf/all/secure_redirects
# Do not send Redirect Messages:
for f in /proc/sys/net/ipv4/conf/*/send_redirects ; do
echo "0" > $f
done
# Disable ICMP Redirect Acceptance:
for f in /proc/sys/net/ipv4/conf/*/accept_redirects ; do
echo "0" > $f
done
# Disable source routed packets as they are ridiculous:
for f in /proc/sys/net/ipv4/conf/*/accept_source_route ; do
echo "0" > $f
done
The effect is the same, but we just went from 30 lines to 7 - that's a lot of screen real estate saved (almost 77%), and I would argue that my 7 lines are much easier to read than your 30. Of course, that's totally subjective - and this is just meant as an illustration of what I mean. In the end, if you feel more comfortable with the 30 lines, then it's definitely what you should stick with.
I was curious about whether or not you understood every line in your script because when you mentioned you had parts from scripts on the Net I suspected perhaps this was some huge copy/paste experiment, which would have been terrible. I'm glad that isn't the case.
Ahh, I made those changes. I didn't realise I could use "all" instead of the wildcard. So that cuts the need out for the for loop in those sections. I updated the script to reflect that.
I try to keep a description of each line though for future reference. If those were taken out it would be a lot cleaner looking but it helps.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.