Iptables (1.4)/firewall6.sh


 * 1) !/bin/bash
 * 2) This is the IPv6 version of the above. Much Copypasta, with a few
 * 3) exceptions, mostly regarding ICMP.
 * 4) This script was developed by Vekseid, available at
 * 5) http://hexwiki.com/wiki/Iptables_(1.4)/firewall6.sh?action=raw
 * 6) Discussed at http://hexwiki.com/wiki/Iptables_(1.4)
 * 7) - vek@vekseid.com
 * 8) This script would not have been possible without Oskar Andreasson's
 * 9) IPTables Tutorial, found at:
 * 10) http://www.frozentux.net/iptables-tutorial/iptables-tutorial.html
 * 11) I additionally made use of a good amount of the information in Jan
 * 12) Engelhardt's "Detecting and deceiving network scans", found here:
 * 13) http://jengelh.medozas.de/documents/Chaostables.pdf
 * 1) I additionally made use of a good amount of the information in Jan
 * 2) Engelhardt's "Detecting and deceiving network scans", found here:
 * 3) http://jengelh.medozas.de/documents/Chaostables.pdf

export IPT=/sbin/ip6tables export SELFIPS="2604:4500:0:7::/64 2604:4500::e02 2604:4500::e03" export WHITELIST="2607:f128:4a:2::/64" export TRUSTEDFACES="lo" export BLACKLIST="" export SSHIP="2604:4500:0:7:e::9" export SSHPORT=23728 export SAFEIPS="2604:4500:0:7:3::2 2604:4500:0:7:1::7" export SERVIPS="2604:4500:0:7:3::2" export TARPORTS=25 export SERVPORTS="587,993" export OPENPORTS="80,443,25565" export UDPIPS="" export UDPPORTS="" export ALLOWPING=1 export USELOG=1
 * 1) Define variables to make for easy tuning.
 * 2) IPT - Location of the iptables binary
 * 3) SELFIPS      - The server's allocated IP addresses (Elliquiy's, here)
 * 4) WHITELIST    - My own personal IPs, separated by spaces, CIDR style
 * 5)                for address blocks e.g. 127.0.0.0/8
 * 6) TRUSTEDFACES - Interfaces we trust, typically lo but could also have
 * 7)                e.g. eth1 in a two-server setup. Space separated
 * 8) BLACKLIST    - Hated IPs. Functions as whitelist.
 * 9) SSHIP        - IP address for SSH
 * 10) SAFEIPS      - Won't tarpit on this IP/mask
 * 11) SERVIPS      - Running SERVPORTS on this IP/mask
 * 12) SSHPORT      - The port I have SSH set to.
 * 13) TARPORTS     - Ports we are going to tarpit when they get hit
 * 14)                improperly. Default to 25 (SMTP) to trap spambots.
 * 15) SERVPORTS    - Ports only open on the service IP
 * 16) OPENPORTS    - Chosen ports to open on all IPs.
 * 17) UDPIPS       - Space-separated list of IP addresses/masks to permit
 * 18)                UDP on.
 * 19) UDPPORTS     - Comma-separated list of ports to allow UDP.
 * 20) ALLOWPING    - Whether or not to allow public pings. I often have to
 * 21)                diagnose problems for my members so sure, why not : )
 * 22) USELOG       - Whether to use the basic log. Nothing in these logs
 * 23)                are fully reliable so I want to make them easy to
 * 24)                disable.
 * 1)                disable.

export CONNREPORT="-m connlimit --connlimit-above 256 --connlimit-mask 56" export CONNLIMIT="-m connlimit --connlimit-above 512 --connlimit-mask 56" export LOGLEVEL="--log-level debug --log-ip-options" export LOGCON="--log-level debug --log-ip-options --log-tcp-sequence --log-tcp-options"
 * 1) The following are 'more advanced' variables.
 * 2) CONNREPORT   - While the limit is initially far higher, we want to
 * 3)                be reporting far before then, to see how many
 * 4)                legitimate users a blanket cutoff may restrict in
 * 5)                the event of an attack.
 * 6) CONNLIMIT    - The connlimit match declaration - it declares how
 * 7)                many tcp connections may exist for a given IP block.
 * 8) LOGLEVEL     - Logging line for basic logging.
 * 9) LOGCON       - Logs more serious incidents - connection flooding and
 * 10)                so on, that we want more reliable data for.
 * 1) LOGCON       - Logs more serious incidents - connection flooding and
 * 2)                so on, that we want more reliable data for.

export HASHICMP="-m hashlimit --hashlimit-upto 60/second --hashlimit-burst 240 --hashlimit-mode srcip --hashlimit-srcmask 56 --hashlimit-name icmp --hashlimit-htable-size 8192 --hashlimit-htable-max 8192 --hashlimit-htable-gcinterval 1000 --hashlimit-htable-expire 2000" export HASHSSH="-m hashlimit --hashlimit-upto 3/minute --hashlimit-burst 3 --hashlimit-mode srcip --hashlimit-srcmask 64 --hashlimit-name ssh --hashlimit-htable-size 8192 --hashlimit-htable-max 8192 --hashlimit-htable-gcinterval 3000 --hashlimit-htable-expire 60000" export HASHLOG="-m hashlimit --hashlimit-upto 2/minute --hashlimit-burst 240 --hashlimit-mode srcip --hashlimit-srcmask 56 --hashlimit-name log --hashlimit-htable-size 8192 --hashlimit-htable-max 8192 --hashlimit-htable-gcinterval 3000 --hashlimit-htable-expire 120000" export HASHCON="-m hashlimit --hashlimit-upto 2/minute --hashlimit-burst 240 --hashlimit-mode srcip --hashlimit-srcmask 56 --hashlimit-name con --hashlimit-htable-size 8192 --hashlimit-htable-max 8192 --hashlimit-htable-gcinterval 3000 --hashlimit-htable-expire 120000"
 * 1) The documentation on hashlimit could certainly use refinement. Worse,
 * 2) many examples might trick someone into using limit where a well-tuned
 * 3) hashlimit is really what they want - if they really want to take the
 * 4) performance hit at all.
 * 5) The following comes from reading the kernel module source, not the
 * 6) documentation : ) The man pages are not very helpful and the tutorial
 * 7) is extremely misleading on this match.
 * 8) --hashlimit-htable-gcinterval is always set to three seconds in these
 * 9)   examples, except for ping, but you may wish to slow this down if
 * 10)   you find your system cpu usage getting high under heavy loads.
 * 11)   Your load is going to be based loosely off of htable-size divided
 * 12)   by gcinterval. The default is 1000 (one second).
 * 13) --hashlimit-htable-expire is an easy one to calculate - just pick the
 * 14)   time when the hashlimit-upto/above will fill up your bucket, maybe
 * 15)   add a bit extra, or less if you don't care about occasional
 * 16)   overages. The default is 10000 (ten seconds).
 * 17) --hashlimit-htable-max to quote the current kernel source:
 * 18)   /* FIXME: do something. question is what.. */
 * 19)   It currently fires a kernel warning if the hash table is allowed
 * 20)   to grow beyond this size. It defaults to 8 times the htable-size,
 * 21)   and has a floor of htable-size if set to a low value.
 * 22)   There's no actual limit, however. I'm not convinced that the
 * 23)   hashlimit algorithm is all it could be >_>
 * 24)   I set this to htable-size since if somehow eight thousand
 * 25)   connections are open I rather want to be warned about it.
 * 26) --hashlimit-htable-size is the size of the hash index. A hash of
 * 27)   log(htable-size) is computed for whatever was given in mode/mask.
 * 28)   If two objects end up with the same hash, they get placed in a
 * 29)   chain which is iteratively searched.
 * 30)   DO NOT SET THIS LOW EXPECTING IT WILL THROTTLE A DDOS. In theory,
 * 31)   that is what htable-max is for. But only in theory.
 * 32)   It has a bit of a messy default:
 * 33)   num_physpages * page_size / 16384, with a cap of 8192 and a minimum
 * 34)   of 16. Pretty much anyone with 256mb+ of RAM is going to reach the
 * 35)   cap.
 * 36)   In addition to the basic memory for the table itself, you will
 * 37)   allocate pointer_bytes * 2 * htable-size in bytes for the table.
 * 38)   More memory gets allocated in other functions and I haven't fully
 * 39)   gone through the source, but for an amd64 machine that means 16
 * 40)   bytes per bucket.
 * 41)   Since this is the size of the full index and I have RAM to spare, I
 * 42)   set all of the tables to 8k. The main thing to worry about here is
 * 43)   the garbage collection interval, since this means it's checking
 * 44)   eight thousand -linked lists- every interval.
 * 45) --hashlimit-srcmask is probably best set to /29 for IPv4 in most
 * 46)   situations where srcip is used for the tuple. Not only does this
 * 47)   help reduce collision rates, /29's are often the same family or
 * 48)   local organization. It works fine to treat them in this manner.
 * 49)   The default for this and dstmask is 32 for IPv4 and 128 for IPv6.
 * 50)   If using IPv6, if you do not set this to at least as low as /64 you
 * 51)   are insane.
 * 52) --hashlimit-mode is a fairly straightforward setting. I would suggest
 * 53)   using separate hashes for different ports and destination ips for
 * 54)   most scenarios.
 * 55) --hashlimit-burst defaults to five. This determines the maximum size
 * 56)   of the bucket which gets filled by upto/above.
 * 57) HASHLOG    - The hashlimit declaration for basic logging. It's rather
 * 58)              heavily limited in order to keep us from flooding.
 * 59) HASHCON    - Log mass connection attempts
 * 60) HASHSSH    - Not needed with this current setup, it exists more to
 * 61)              limit getting my auth log slammed than anything.
 * 62) HASHICMP   - Accept all but the most crazy degrees of icmp madness.
 * 1) HASHCON    - Log mass connection attempts
 * 2) HASHSSH    - Not needed with this current setup, it exists more to
 * 3)              limit getting my auth log slammed than anything.
 * 4) HASHICMP   - Accept all but the most crazy degrees of icmp madness.

export DROPTARGET=DROP
 * 1) Here we set some variables that are not 'user modified'.
 * 1) Here we set some variables that are not 'user modified'.
 * 1) if [ $USELOG -eq 1 ] ; then
 * 2)  export DROPTARGET=DRP
 * fi

$IPT -F $IPT -X $IPT -t raw -F $IPT -t raw -X $IPT -P INPUT DROP $IPT -P FORWARD DROP $IPT -P OUTPUT ACCEPT
 * 1) Flush current rules and reset policies.
 * 1) Flush current rules and reset policies.

sleep 3
 * 1) Give the system some time to rest. Can be important if it's been
 * 2) tracking a lot.
 * 1) tracking a lot.

for i in $TRUSTEDFACES do $IPT -t raw -A PREROUTING -i $i -j NOTRACK $IPT -A INPUT -i $i -j ACCEPT done
 * 1) Don't track our interfaces we trust.
 * 1) Don't track our interfaces we trust.

##################################################################### # Log dropped packets. Only make the chain if logging is on. # This is only really useful to determine if you are under a serious # attack of some sort. ##################################################################### #####################################################################
 * 1) if [ $USELOG -eq 1 ] ; then
 * 1)  $IPT -N DRP
 * 2)  $IPT -A DRP $HASHLOG -j LOG $LOGLEVEL --log-prefix "IP6Tables: Dropped: "
 * 3)  $IPT -A DRP -j DROP
 * fi

for i in $WHITELIST do $IPT -A INPUT -p tcp -s $i -j ACCEPT done
 * 1) Accept from established/related connections and our whitelist.
 * 2) Drop invalid sources and non-unicast # packets/sources outright, as
 * 3) well as killing funny business.
 * 4) Iterate through whitelist entries
 * 1) Iterate through whitelist entries
 * 1) Iterate through whitelist entries

for i in $BLACKLIST do $IPT -A INPUT -s $i -j $DROPTARGET done
 * 1) Iterate through blacklist entries

for i in $SELFIPS do $IPT -A INPUT -s $i -j $DROPTARGET done
 * 1) Iterate through our own ips - drop spoofed entries.

$IPT -A INPUT -p ipv6-icmp -j ACCEPT
 * 1) ICMP seems to be a lot more relevant in IPv6

$IPT -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
 * 1) I used to split out tcp traffic and rate limit that. It really only
 * 2) caught exceptionally bad ISPs with legitimate users and aggressive
 * 3) web spiders. DDOS attempts are best mitigated with connlimit and
 * 4) possibly checking for lots of very small packets.
 * 5) I've found that the INVALID state actually spends most of its time
 * 6) dropping legitimate traffic. I can't really recommend it. You can
 * 7) do just as well by being picky with what you accept for NEW
 * 8) connections.
 * 1) do just as well by being picky with what you accept for NEW
 * 2) connections.

$IPT -A INPUT -m pkttype ! --pkt-type unicast -j $DROPTARGET $IPT -A INPUT -m addrtype ! --src-type UNICAST -j $DROPTARGET
 * 1) Drop garbage sources and destinations.

$IPT -N TCPMESS $IPT -A TCPMESS -p tcp -m statistic --mode random --probability 0.04 -j REJECT $IPT -A TCPMESS -j DROP
 * 1) TCPMESS is our version of the CHAOS target.
 * 2) The primary purpose of this is not even to deceive, but simply to
 * 3) increase the cost of portscanning. It has a secondary purpose of
 * 4) obscuring potentially sensitive ports, like SSH.
 * 1) obscuring potentially sensitive ports, like SSH.
 * 1) $IPT -A TCPMESS -p tcp -m statistic --mode random --probability 0.03 -j DELUDE

$IPT -N TCPIN $IPT -A TCPIN -m recent --update --seconds 900 --hitcount 1 --name flooders -j DROP $IPT -A TCPIN -p tcp $CONNREPORT $HASHCON -j LOG $LOGCON --log-prefix "Hackers6: Many Connections: " $IPT -A TCPIN -p tcp $CONNREPORT $HASHCON -m state --state INVALID -j $DROPTARGET $IPT -A TCPIN -p tcp $CONNLIMIT -m recent --set --name flooders $IPT -A TCPIN -p tcp $CONNLIMIT -j LOG $LOGCON --log-prefix "Hackers6: Connection Overlimit: " $IPT -A TCPIN -p tcp $CONNLIMIT -j REJECT --reject-with tcp-reset $IPT -A TCPIN -p tcp --tcp-flags SYN,FIN,RST,PSH,URG SYN -j ACCEPT $IPT -A TCPIN -p tcp --tcp-flags SYN,ACK,RST,URG ACK -j ACCEPT $IPT -A TCPIN -p tcp --tcp-flags SYN,FIN,RST,PSH,URG RST -j ACCEPT if [ $USELOG -eq 1 ] ; then $IPT -A TCPIN $HASHLOG -j LOG $LOGLEVEL --log-prefix "IP6Tables: Invalid Connect: " fi $IPT -A TCPIN -j DROP
 * 1) New TCP Traffic going to valid ports gets sent here.
 * 2) Check connlimit, check new connection rates, log nonsense.
 * 1) Check connlimit, check new connection rates, log nonsense.
 * 1) Sometimes we see new connections from legitimate peoples that
 * 2) somehow escaped proper connection tracking. These are most
 * 3) frequently ACK, followed by RST, followed distantly by ACK PSH.
 * 1) frequently ACK, followed by RST, followed distantly by ACK PSH.

$IPT -A INPUT -p tcp -m multiport --dports $OPENPORTS -j TCPIN for i in $SERVIPS do $IPT -A INPUT -p tcp -d $i -m multiport --dports $SERVPORTS -j TCPIN done for i in $SAFEIPS do $IPT -A INPUT -p tcp -d $i -m multiport --dports $TARPORTS -j TCPIN done $IPT -A INPUT -p tcp -m multiport --dports $TARPORTS -j DROP
 * 1) TCP traffic for our standard ports are not hindered for the purposes
 * 2) of automated blocking of general hijinks.
 * 3) Spammers trying to access port 25 on IPs I'm only using for hosting
 * 4) get tarpitted. Otherwise, we accept things on open ports, except for
 * 5) our secret (in this case, our SSH port), and we shut people poking
 * 6) around for a few hours.
 * 1) our secret (in this case, our SSH port), and we shut people poking
 * 2) around for a few hours.
 * 1) $IPT -A INPUT -p tcp ! -d $SAFEIP -m multiport --dports $TARPORTS -j TARPIT

$IPT -A INPUT -p tcp -m recent --update --seconds 3600 --hitcount 1 --name scanners -j TCPMESS $IPT -A INPUT -p tcp -d $SSHIP --dport $SSHPORT $HASHSSH -j ACCEPT $IPT -A INPUT -p tcp -d $SSHIP --dport $SSHPORT $HASHCON -j LOG $LOGCON --log-prefix "Hackers6: SSH Flood: " $IPT -A INPUT -p tcp -m recent --set --name scanners $IPT -A INPUT -p tcp -d $SSHIP --dport $SSHPORT -j TCPMESS if [ $USELOG -eq 1 ] ; then $IPT -A INPUT -p tcp $HASHLOG -j LOG $LOGLEVEL --log-prefix "IP6Tables: Scanner: " fi $IPT -A INPUT -p tcp -j TCPMESS


 * 1) Overall ICMP Rules
 * 2) Because ICMP is effectively a new protocol in IPv6, I'm being a lot
 * 3) more liberal in what I accept.
 * 1) more liberal in what I accept.


 * 1) Allow icmp packets at the rate given in HASHICMP and log flood
 * 2) attempts.
 * 3) Commented out for now until more learnings can be had.
 * 4) $IPT -A INPUT -p ipv6-icmp -m state --state NEW $HASHICMP -j ACCEPT
 * 5) if [ $USELOG -eq 1 ] ; then
 * 6)  $IPT -A INPUT -p ipv6-icmp -m state --state NEW $HASHLOG -j LOG $LOGLEVEL --log-prefix "IP6Tables: ICMP Flood: "
 * fi
 * 1) $IPT -A INPUT -p ipv6-icmp -j DROP
 * 1)  $IPT -A INPUT -p ipv6-icmp -m state --state NEW $HASHLOG -j LOG $LOGLEVEL --log-prefix "IP6Tables: ICMP Flood: "
 * fi
 * 1) $IPT -A INPUT -p ipv6-icmp -j DROP

$IPT -N UDPFUN $IPT -A UDPFUN -m statistic --mode random --probability 0.04 -j REJECT $IPT -A UDPFUN -j DROP for i in $UDPIPS do $IPT -A INPUT -p udp -d $i -m multiport --dports $UDPPORTS -j ACCEPT done $IPT -A INPUT -p udp -j UDPFUN
 * 1) UDP Rules.
 * 2) Not running DNS, so, let's mess with scanners!
 * 3) Probability in the .03-.04 range is apparently ideal.
 * 4) If you are more concerned about confusing scans of your network as
 * 5) opposed to scans of a single IP, using proto-unreach liberally can
 * 6) confuse protocol scans.
 * 1) opposed to scans of a single IP, using proto-unreach liberally can
 * 2) confuse protocol scans.
 * 1) Recording UDP scans is largely wasted space.
 * 2) if [ $USELOG -eq 1 ] ; then
 * 3)  $IPT -A UDPFUN $HASHLOG -j LOG $LOGLEVEL --log-prefix "IP6Tables: UDP: "
 * fi
 * 1) UDP rules -must- come after dropping spoofed addresses.
 * 1) UDP rules -must- come after dropping spoofed addresses.


 * 1) This script was developed by Vekseid at
 * 2) http://hexwiki.com/wiki/Iptables_(1.4)/firewall6.sh?action=raw
 * 3) - vek@vekseid.com
 * 1) - vek@vekseid.com