Iptables (1.4)/firewall6.sh

From Hexwiki
Jump to: navigation, search
  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. 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.
  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.

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. 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.

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 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.
  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.

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. Here we set some variables that are not 'user modified'.


  1. if [ $USELOG -eq 1 ] ; then
  2. export DROPTARGET=DRP
  3. fi
  1. Flush current rules and reset policies.


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

sleep 3

  1. Don't track our interfaces we trust.

for i in $TRUSTEDFACES do

 $IPT -t raw -A PREROUTING -i $i -j NOTRACK
 $IPT -A INPUT -i $i -j ACCEPT


  1. if [ $USELOG -eq 1 ] ; then
 # 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. $IPT -N DRP
  2. $IPT -A DRP $HASHLOG -j LOG $LOGLEVEL --log-prefix "IP6Tables: Dropped: "
  3. $IPT -A DRP -j DROP
  1. fi
  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

for i in $WHITELIST do

 $IPT -A INPUT -p tcp -s $i -j ACCEPT


  1. Iterate through blacklist entries

for i in $BLACKLIST do



  1. Iterate through our own ips - drop spoofed entries.

for i in $SELFIPS do



  1. ICMP seems to be a lot more relevant in IPv6

$IPT -A INPUT -p ipv6-icmp -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. Drop garbage sources and destinations.

$IPT -A INPUT -m pkttype ! --pkt-type unicast -j $DROPTARGET $IPT -A INPUT -m addrtype ! --src-type UNICAST -j $DROPTARGET

  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. $IPT -A TCPMESS -p tcp -m statistic --mode random --probability 0.03 -j DELUDE

$IPT -A TCPMESS -p tcp -m statistic --mode random --probability 0.04 -j REJECT $IPT -A TCPMESS -j DROP

  1. New TCP Traffic going to valid ports gets sent here.
  2. Check connlimit, check new connection rates, log nonsense.

$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

  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.

$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: "


  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.

$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


  1. $IPT -A INPUT -p tcp ! -d $SAFEIP -m multiport --dports $TARPORTS -j TARPIT

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

$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. 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: "
  7. fi
  8. $IPT -A INPUT -p ipv6-icmp -j DROP
  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. 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: "
  4. fi

$IPT -A UDPFUN -m statistic --mode random --probability 0.04 -j REJECT $IPT -A UDPFUN -j DROP

  1. UDP rules -must- come after dropping spoofed addresses.

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. This script was developed by Vekseid at
  2. http://hexwiki.com/wiki/Iptables_(1.4)/firewall6.sh?action=raw
  3. - vek@vekseid.com