diff options
Diffstat (limited to 'firewall')
-rw-r--r-- | firewall | 357 |
1 files changed, 181 insertions, 176 deletions
@@ -1,179 +1,184 @@ | |||
1 | # Make sure we have all the commands to continue | 1 | #!/bin/bash |
2 | if [[ ! `which iptables` || ! `which ifconfig` || ! `which grep` || ! `which sed` ]]; then | 2 | # |
3 | echo 'Essential commands are missing. Can not continue.' | 3 | # Iptables Setup and Initialization Script |
4 | exit 1 | 4 | # Version 1.0 |
5 | fi | 5 | # |
6 | # Written by Michael Crute (mcrute@gmail.com) | ||
7 | # for SoftGroup Interactive on July 10, 2006 | ||
8 | # Last updated: same | ||
9 | # | ||
6 | 10 | ||
7 | # Check for root | 11 | if [ $UID != 0 ]; then |
8 | if [[ $UID != 0 ]]; then | 12 | echo "You are not root. Goodbye." |
9 | echo 'You are not root.' | 13 | exit 1 |
10 | exit 1 | ||
11 | fi | 14 | fi |
12 | 15 | ||
13 | # First set LC_ALL to en to avoid l10n problems when awk-ing IPs etc. | 16 | IPT='/sbin/iptables' |
14 | export LC_ALL="en" | 17 | |
15 | 18 | GREEN='\033[0;32m' | |
16 | # Source our configuration file | 19 | WHITE='\033[0m' |
17 | source /etc/firewall.conf | 20 | RED='\033[0;31m' |
18 | 21 | ||
19 | # Go into lockdown mode while we setup the rules | 22 | ALLOW_PING=0 |
20 | iptables -P INPUT DROP | 23 | |
21 | iptables -P OUTPUT DROP | 24 | function do_log |
22 | iptables -P FORWARD DROP | 25 | { |
23 | 26 | timestamp=`date +"[%Y-%m-%d %H:%M:%S]"` | |
24 | # Flush all existing chains and erase personal chains | 27 | if [ $2 == 0 ]; then |
25 | CHAINS=`cat /proc/net/ip_tables_names 2>/dev/null` | 28 | echo -e "$timestamp $1: [$GREEN OK $WHITE]" |
26 | for i in $CHAINS; do | 29 | else |
27 | iptables -t $i -F | 30 | echo -e "$timestamp $1: [$RED FAILED $WHITE]" |
28 | iptables -t $i -X | 31 | fi |
29 | done | 32 | } |
30 | echo 1 > /proc/sys/net/ipv4/tcp_syncookies | 33 | |
31 | echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts | 34 | function flush_all |
32 | 35 | { | |
33 | # Source Address Verification | 36 | # Flush all existing chains and erase personal chains |
34 | for f in /proc/sys/net/ipv4/conf/*/rp_filter; do | 37 | CHAINS=`cat /proc/net/ip_tables_names 2>/dev/null` |
35 | echo 1 > $f | 38 | for i in $CHAINS; do |
36 | done | 39 | $IPT -t $i -F |
37 | 40 | $IPT -t $i -X | |
38 | # Disable IP source routing and ICMP redirects | 41 | do_log "Flushing chain $i" $? |
39 | for f in /proc/sys/net/ipv4/conf/*/accept_source_route; do | 42 | done |
40 | echo 0 > $f | 43 | |
41 | done | 44 | # Flush the conntrack database if we can |
42 | for f in /proc/sys/net/ipv4/conf/*/accept_redirects; do | 45 | if [ `which conntrack > /dev/null 2>&1` ]; then |
43 | echo 0 > $f | 46 | conntrack -F |
44 | done | 47 | do_log "Flushing conntrack" $? |
45 | echo 1 > /proc/sys/net/ipv4/ip_forward | 48 | fi |
46 | 49 | ||
47 | # Determine the IP/Broadcast/Netmask for the outside interface | 50 | $IPT -P INPUT ACCEPT |
48 | # dynamically by grepping ifconfig commands | 51 | do_log "All chains flushed" $? |
49 | # | 52 | } |
50 | # Due to absence of EXTBC in ifconfig output I manually set it | 53 | |
51 | # to 255.255.255.255 this hopefully will serve the same purpose | 54 | function set_ping |
52 | EXTIP="`ifconfig $EXTIF|grep addr:|sed 's/.*addr:\([^ ]*\) .*/\1/'`" | 55 | { |
53 | EXTBC="255.255.255.255" | 56 | policy="ACCEPT" |
54 | EXTMSK="`ifconfig $EXTIF|grep Mask:|sed 's/.*Mask:\([^ ]*\)/\1/'`" | 57 | [[ $1 == 0 ]] && policy="DROP" |
55 | EXTNET="$EXTIP/$EXTMSK" | 58 | |
56 | echo "EXTIP=$EXTIP EXTBC=$EXTBC EXTMSK=$EXTMSK EXTNET=$EXTNET" | 59 | $IPT -A INPUT -p icmp --icmp-type 8 -j $policy |
57 | 60 | do_log "$policy pings" $? | |
58 | # Determine the IP/Broadcast/Netmask for the outside interface | 61 | } |
59 | # dynamically by grepping ifconfig commands | 62 | |
60 | INTIP="`ifconfig $INTIF|grep addr:|sed 's/.*addr:\([^ ]*\) .*/\1/'`" | 63 | function block_port |
61 | INTBC="`ifconfig $INTIF|grep Bcast:|sed 's/.*Bcast:\([^ ]*\) .*/\1/'`" | 64 | { |
62 | INTMSK="`ifconfig $INTIF|grep Mask:|sed 's/.*Mask:\([^ ]*\)/\1/'`" | 65 | $IPT -A INPUT -p $1 -m state --state NEW -m $1 --dport $2 -j DROP |
63 | INTNET="$INTIP/$INTMSK" | 66 | $IPT -A OUTPUT -p $1 -m state --state NEW -m $1 --dport $2 -j DROP |
64 | echo "INTIP=$INTIP INTBC=$INTBC INTMSK=$INTMSK INTNET=$INTNET" | 67 | do_log "Blocking $1 port $2" $? |
65 | 68 | } | |
66 | # We are now going to create a few custom chains that will result in | 69 | |
67 | # logging of dropped packets. This will enable us to avoid having to | 70 | function load_policy |
68 | # enter a log command prior to every drop we wish to log. The | 71 | { |
69 | # first will be first log drops the other will log rejects. | 72 | policy=`cat /etc/firewall/profile 2>/dev/null || echo 'default'` |
70 | # Do not complain if chain already exists (so restart is clean) | 73 | [[ ! -z "$1" ]] && policy=$1 |
71 | iptables -N DROPl 2> /dev/null | 74 | LOADFILE="/etc/firewall/iptables-$policy" |
72 | iptables -A DROPl -j LOG --log-prefix 'DROPl:' | 75 | |
73 | iptables -A DROPl -j DROP | 76 | if [ -r $LOADFILE ]; then |
74 | iptables -N REJECTl 2> /dev/null | 77 | . $LOADFILE |
75 | iptables -A REJECTl -j LOG --log-prefix 'REJECTl:' | 78 | flush_all |
76 | iptables -A REJECTl -j REJECT | 79 | do_log "Loading ruleset $LOADFILE" $? |
77 | 80 | else | |
78 | # Now we are going to accpet all traffic from our loopback device | 81 | do_log "Could not load a ruleset" 1 |
79 | # if the IP matches any of our interfaces. | 82 | exit 1 |
80 | iptables -A INPUT -i $LPDIF -s $LPDIP -j ACCEPT | 83 | fi |
81 | iptables -A INPUT -i $LPDIF -s $EXTIP -j ACCEPT | 84 | } |
82 | iptables -A INPUT -i $LPDIF -s $INTIP -j ACCEPT | 85 | |
83 | 86 | function filter_host | |
84 | # Blocking Broadcasts | 87 | { |
85 | iptables -A INPUT -i $EXTIF -d $EXTBC -j DROPl | 88 | $IPT -I INPUT -s $2 -j $1 |
86 | iptables -A INPUT -i $INTIF -d $INTBC -j DROPl | 89 | do_log "$1 host $2" $? |
87 | iptables -A OUTPUT -o $EXTIF -d $EXTBC -j DROPl | 90 | } |
88 | iptables -A OUTPUT -o $INTIF -d $INTBC -j DROPl | 91 | |
89 | iptables -A FORWARD -o $EXTIF -d $EXTBC -j DROPl | 92 | function filter_port |
90 | iptables -A FORWARD -o $INTIF -d $INTBC -j DROPl | 93 | { |
91 | 94 | $IPT -A INPUT -p $2 -m state --state NEW -m $2 --dport $1 -j $3 | |
92 | # Block WAN access to internal network | 95 | do_log "$3 $2 port $1" $? |
93 | # | 96 | } |
94 | # This also stops nefarious crackers from using our network as a | 97 | |
95 | # launching point to attack other people | 98 | function add_exception |
96 | iptables -A INPUT -i $EXTIF -d ! $EXTIP -j DROPl | 99 | { |
97 | 100 | ip=`echo $1 | cut -d' ' -f1` | |
98 | # Now we will block internal addresses originating from anything but our | 101 | prot=`echo $1 | cut -d' ' -f2` |
99 | # two predefined interfaces... just remember that if you jack your | 102 | port=`echo $1 | cut -d' ' -f3` |
100 | # your laptop or another pc into one of these NIC's directly, you'll need | 103 | |
101 | # to ensure that they either have the same ip or that you add a line explicitly | 104 | $IPT -A INPUT -p $prot -m state --state NEW -s $ip -m $prot --dport $port -j ACCEPT |
102 | # for that IP as well | 105 | |
103 | iptables -A INPUT -i $INTIF -s ! $INTNET -j DROPl | 106 | do_log "Allowing $ip for $prot $port" $? |
104 | iptables -A OUTPUT -o $INTIF -d ! $INTNET -j DROPl | 107 | } |
105 | iptables -A FORWARD -i $INTIF -s ! $INTNET -j DROPl | 108 | |
106 | iptables -A FORWARD -o $INTIF -d ! $INTNET -j DROPl | 109 | function set_defaults |
107 | 110 | { | |
108 | # An additional Egress check | 111 | $IPT -A INPUT -s 127.0.0.1 -j ACCEPT |
109 | iptables -A OUTPUT -o $EXTIF -s ! $EXTNET -j DROPl | 112 | $IPT -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT |
110 | 113 | $IPT -P INPUT DROP | |
111 | # Block outbound ICMP (except for PING) | 114 | $IPT -P FORWARD DROP |
112 | iptables -A OUTPUT -o $EXTIF -p icmp --icmp-type ! 8 -j DROPl | 115 | $IPT -P OUTPUT ACCEPT |
113 | iptables -A FORWARD -o $EXTIF -p icmp --icmp-type ! 8 -j DROPl | 116 | } |
114 | 117 | ||
115 | # Explicitly block TCP ports | 118 | # Lockdown is the most strict policy that only passes |
116 | for i in $TCPBLOCK; do | 119 | # ssh traffic. This is good for new servers and emergencies |
117 | iptables -A INPUT -p tcp --dport $i -j DROPl | 120 | function lockdown |
118 | iptables -A OUTPUT -p tcp --dport $i -j DROPl | 121 | { |
119 | iptables -A FORWARD -p tcp --dport $i -j DROPl | 122 | flush_all |
120 | done | 123 | |
121 | 124 | $IPT -P INPUT DROP | |
122 | # Explicitly block UDP ports | 125 | $IPT -P FORWARD DROP |
123 | for i in $UDPBLOCK; do | 126 | $IPT -P OUTPUT DROP |
124 | iptables -A INPUT -p udp --dport $i -j DROPl | 127 | do_log "All chains set to drop" $? |
125 | iptables -A OUTPUT -p udp --dport $i -j DROPl | 128 | |
126 | iptables -A FORWARD -p udp --dport $i -j DROPl | 129 | $IPT -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT |
127 | done | 130 | $IPT -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT |
128 | 131 | $IPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT | |
129 | # Open inbound service ports | 132 | $IPT -A OUTPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT |
130 | for i in $INPORTS; do | 133 | do_log "Allowing ssh only" $? |
131 | iptables -A INPUT -p tcp --dport $i -j ACCEPT | 134 | |
132 | done | 135 | do_log "Firewall locked down" $? |
133 | 136 | } | |
134 | iptables -A FORWARD -t filter -o $EXTIF -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT | 137 | |
135 | iptables -A FORWARD -t filter -i $EXTIF -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT | 138 | function build_firewall |
136 | 139 | { | |
137 | # Opening up ftp connection tracking | 140 | load_policy $1 |
138 | MODULES="ip_nat_ftp ip_conntrack_ftp" | 141 | set_defaults |
139 | for i in $MODULES; do | 142 | set_ping $ALLOW_PING |
140 | modprobe $i | 143 | |
141 | done | 144 | # Set exceptions |
142 | 145 | for idx in $(seq ${#RULES[@]}); do | |
143 | # Allow inside systems to use external services | 146 | item=${RULES[$idx]} |
144 | for i in $TCPSERV; do | 147 | add_exception $item |
145 | iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP --dport $i --syn -m state --state NEW -j ACCEPT | 148 | done; |
146 | iptables -A FORWARD -i $INTIF -p tcp -s $INTNET --dport $i --syn -m state --state NEW -j ACCEPT | 149 | |
147 | done | 150 | # Allow or deny hosts |
148 | 151 | for host in $HOSTS_DENY; do | |
149 | for i in $UDPSERV; do | 152 | filter_host "DROP" $host |
150 | iptables -A OUTPUT -o $EXTIF -p udp -s $EXTIP --dport $i -m state --state NEW -j ACCEPT | 153 | done |
151 | iptables -A FORWARD -i $INTIF -p udp -s $INTNET --dport $i -m state --state NEW -j ACCEPT | 154 | for host in $HOSTS_ALLOW; do |
152 | done | 155 | filter_host "ALLOW" $host |
153 | 156 | done | |
154 | # Allow to ping out | 157 | |
155 | iptables -A OUTPUT -o $EXTIF -p icmp -s $EXTIP --icmp-type 8 -m state --state NEW -j ACCEPT | 158 | # Allow or deny tcp ports |
156 | iptables -A FORWARD -i $INTIF -p icmp -s $INTNET --icmp-type 8 -m state --state NEW -j ACCEPT | 159 | for port in $TCP_DENY; do |
157 | 160 | block_port "tcp" $port | |
158 | # Allow firewall to ping internal systems | 161 | done |
159 | iptables -A OUTPUT -o $INTIF -p icmp -s $INTNET --icmp-type 8 -m state --state NEW -j ACCEPT | 162 | for port in $TCP_ALLOW; do |
160 | 163 | filter_port $port "tcp" "ACCEPT" | |
161 | # Allow a few services internally | 164 | done |
162 | iptables -A OUTPUT -o $INTIF -p tcp -s $INTNET --dport 80 -m state --state NEW -j ACCEPT | 165 | |
163 | iptables -A OUTPUT -o $INTIF -p tcp -s $INTNET --dport 443 -m state --state NEW -j ACCEPT | 166 | # Allow or deny udp ports |
164 | iptables -A INPUT -i $INTIF -p tcp --dport 22 --syn -m state --state NEW -j ACCEPT | 167 | for port in $UDP_DENY; do |
165 | 168 | block_port "udp" $port | |
166 | # Setup dynamic NAT | 169 | done |
167 | iptables -t nat -A PREROUTING -j ACCEPT | 170 | for i in $UDP_ALLOW; do |
168 | iptables -t nat -A POSTROUTING -o $EXTIF -s $INTNET -j MASQUERADE | 171 | filter_port $port "udp" "ACCEPT" |
169 | iptables -t nat -A POSTROUTING -j ACCEPT | 172 | done |
170 | iptables -t nat -A OUTPUT -j ACCEPT | 173 | } |
171 | iptables -A INPUT -p tcp --dport auth --syn -m state --state NEW -j ACCEPT | 174 | |
172 | iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT | 175 | if [[ $1 == "--flush" ]]; then |
173 | iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT | 176 | flush_all |
174 | iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT | 177 | exit 0 |
175 | 178 | elif [[ $1 == "--lockdown" ]]; then | |
176 | # Block and log what me may have forgot | 179 | lockdown |
177 | iptables -A INPUT -j DROPl | 180 | exit 0 |
178 | iptables -A OUTPUT -j REJECTl | 181 | else |
179 | iptables -A FORWARD -j DROPl \ No newline at end of file | 182 | build_firewall $1 |
183 | do_log "Firewall started" $? | ||
184 | fi | ||