
{"id":248,"date":"2016-11-10T19:26:24","date_gmt":"2016-11-10T18:26:24","guid":{"rendered":"http:\/\/3ronco.vahanus.net\/?p=248"},"modified":"2019-02-07T19:47:48","modified_gmt":"2019-02-07T18:47:48","slug":"ipturntables-sh","status":"publish","type":"post","link":"http:\/\/3ronco.vahanus.net\/?p=248","title":{"rendered":"Rocking iptables like a DJ"},"content":{"rendered":"<address>turn|table, turn\u00b7ta\u00b7ble (t\u00fbrn t b l), \/\u02c8t\u0259\u02d0nte\u026ab(\u0259)l<\/address>\n<h2>Definition of turntable in English:<\/h2>\n<h3>noun<\/h3>\n<ol>\n<li>\n<ul>\n<li>The circular horizontal rotating platform of a phonograph on which the record is placed.<\/li>\n<li>A phonograph exclusive of amplifying circuitry and speakers.<\/li>\n<li>(turntables) A set of two or more record decks connected to sound mixing equipment, used by a DJ: the two DJs who preside over the turntables play all kinds of cool electronica.<\/li>\n<\/ul>\n<\/li>\n<li>A circular horizontal rotating platform equipped with a railway track, used for turning locomotives, as in a roundhouse.<\/li>\n<li>A rotating platform or disk, such as a lazy Susan.<\/li>\n<li><span style=\"color: #0000ff;\">(ipturntables.sh) A <a href=\"https:\/\/www.gnu.org\/software\/bash\/\">bash<\/a> script with a set of easy, common <a href=\"http:\/\/iptables.org\/\">iptables<\/a> rules forming a firewall to protect a computer host from malicous data packets sent from the internet, used by an Admin.<\/span><\/li>\n<\/ol>\n<p><a href=\"https:\/\/gitlab.vahanus.com\/3ronco\/ipturntables\">1<\/a> ipturntables.sh gitlab repository<br \/>\n<a href=\"http:\/\/en.wikibooks.org\/wiki\/Communication_Networks\/IP_Tables\">2<\/a> The netfilter framework (iptables)<br \/>\n<!--nextpage--><\/p>\n<h2>What is <em>ipturntables.sh<\/em>?<\/h2>\n<p><strong>ipturntables.sh<\/strong> is a bash script controlling a set of abstract firewall rules. Mainly it uses <em>iptables<\/em> and <em>ip<\/em> command to configure a firewall for both <em>IPv4<\/em> and <em>IPv6<\/em> protocols simultaneosly. Most of it&#8217;s functions are reentrant and can be invoked dynamically without reseting the whole firewall but it can also work with static configurations.<br \/>\nThe ruleset is highly optimized to keep rule count small and works in a <em>&#8220;Deny All,\u00a0Allow explicit only&#8221;<\/em> fashion as a stateful firewall and can handle multihome scenarios very well.<br \/>\nOften a functionality of allowing and filtering packets spans multiple chains and can not be limited to a single rule therefore this script&#8217;s approach is to combine (not necessarily multiple) rules into an easy understandable, comprehensive name. Maybe it can be called an abstract <em>iptables<\/em> function or call. A full firewall is then assembled by a set of these most common cases as calls like <strong>BASE_RULE_SET<\/strong> &#8230;, <strong>ALLOW_SUBNET<\/strong> &#8230;, <strong>FORWARD_SUBNET<\/strong> &#8230;, etc.<\/p>\n<p>Although some kind of syntax simplification is used this script doesn&#8217;t try to achieve this by simplifying <em>iptables<\/em> arguments itself like eg. <a href=\"https:\/\/wiki.ubuntu.com\/UncomplicatedFirewall\">UFW<\/a> does therefore it finally just outputs a rules file by calling\u00a0 <em>iptables-save<\/em> command. The idea behind this is to avoid <em>iptables<\/em> micro management by using a combination of a set of well defined firewall filter functions, like a DJ who uses a mix of records for his art instead of composing the music, <em>ipturntables<\/em> is an approach to handle a firewall the same way.<br \/>\nMost serious admins won&#8217;t trust a &#8220;script&#8221; when it comes to firewall security but that&#8217;s ok. You need to be familiar with <a href=\"http:\/\/www.netfilter.org\/projects\/iptables\">iptables<\/a> anyway in order to understand what it does or you can just study the source code therefore it can be used as a good starting point for customized configurations without going too much into implementation details.<\/p>\n<p>But there&#8217;s more <em>ipturntables.sh<\/em> maintains some kind of simple resource tracking for rules created by an abstract call therefore it can remove all rules of such a call cleanly without the need to reconfigure the whole firewall. This makes it possible to tune the firewall dynamically during runtime for different scenarios like multi-homed hosts with multiple interfaces coming up and going down which eases configuration complexity where usally multiple different profiles are used for such a task. Here&#8217;s a subset of features:<\/p>\n<ul>\n<li>ALLOW_DHCP_CLIENT<\/li>\n<li>ALLOW_SUBNETS<\/li>\n<li>ALLOW_LINK_LOCAL<\/li>\n<li>ALLOW_SERVICE_DISCOVERY<\/li>\n<li>ALLOW_TUNNEL<\/li>\n<li>FORWARD_SUBNET (FORWARD_SUBNET_PROTECTIVE)<\/li>\n<li>FORWARD_PORT|FORWARD_ROUTING<\/li>\n<li>MAC_FILTER<\/li>\n<li>POSTROUTING_MASQUERADE<\/li>\n<\/ul>\n<p>At first glance most of this stuff might look simple but in fact some of these functions do really complex things although this is not a documentation i would like to explain the rules in detail for at least some of them to give you an insight of the inner mechanics and principles of the rules setup used.<\/p>\n<p>Thanks to Mark Oellermann and VRT Systems for providing a nice set of shapes for the graphics.<\/p>\n<h2>Creating a base config<\/h2>\n<p>Let&#8217;s start with the scenario used. A typical linux server used as a router with 3 network interfaces with one interface offering public internet connection through a cable modem or DSL or whatever.<\/p>\n<div id=\"attachment_644\" style=\"width: 640px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-644\" class=\"wp-image-644\" src=\"http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_setup-300x235.jpg\" width=\"630\" height=\"494\" srcset=\"http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_setup-300x235.jpg 300w, http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_setup-768x602.jpg 768w, http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_setup-624x489.jpg 624w, http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_setup.jpg 942w\" sizes=\"auto, (max-width: 630px) 100vw, 630px\" \/><p id=\"caption-attachment-644\" class=\"wp-caption-text\">Figure A: Example scenario used.<\/p><\/div>\n<p>Although adding rules dynamically offers fexibility most of the base configuration on a router are long living rules which can be created statically eg. with a simple Makefile:<\/p>\n<pre>#!\/usr\/bin\/make\n\nall: IPv4.rules IPv6.rules\n\nIPv4.rules:\n\u00a0\u00a0 \u00a0.\/ipturntables.sh -4 \\\n\u00a0\u00a0 \u00a0KERNEL_PARAMS accept_source_route,accept_redirects,rp_filter,ip_forward \\\n\u00a0\u00a0 \u00a0PROBE_KERNEL_MODS ip_tables,nf_conntrack \\\n\u00a0\u00a0 \u00a0RESET \\\n\u00a0\u00a0 \u00a0BASE_RULE_SET \\\n\u00a0\u00a0 \u00a0ALLOW_SERVICE_DISCOVERY eth0 \\\n\u00a0\u00a0 \u00a0ALLOW_SUBNETS eth0 \\\n\u00a0\u00a0 \u00a0FORWARD_SUBNET_PROTECTIVE 192.168.0.0\/16 ppp0 \\\n\u00a0\u00a0 \u00a0POSTROUTING_MASQUERADE 192.168.0.0\/16 ppp0 \\\n\u00a0\u00a0 \u00a0&gt;IPv4.rules\n\nIPv6.rules:\n\u00a0\u00a0 \u00a0.\/ipturntables.sh -6 \\\n\u00a0\u00a0 \u00a0KERNEL_PARAMS accept_source_route,accept_redirects,accept_ra,forwarding \\\n\u00a0\u00a0 \u00a0PROBE_KERNEL_MODS ip6_tables,nf_conntrack \\\n\u00a0\u00a0 \u00a0RESET \\\n\u00a0\u00a0 \u00a0BASE_RULE_SET \\\n\u00a0\u00a0 \u00a0ALLOW_SERVICE_DISCOVERY eth0 \\\n\u00a0\u00a0 \u00a0ALLOW_SUBNETS eth0 \\\n\u00a0\u00a0 \u00a0ALLOW_DHCP_CLIENT ppp0 \\\n\u00a0\u00a0 \u00a0&gt;IPv6.rules\n\n[...]<\/pre>\n<p>The resulting IPv?.rules files are created by <em>iptables-save<\/em> command. The <strong>KERNEL_PARAM<\/strong> and <strong>PROBE_KERNEL_MODS<\/strong> just ensure that specific features of iptables are available eg. connection tracking is a feature used in most stateful firewalls today have a look at the manual for details. The <strong>RESET<\/strong> function is pretty obvious, it flushes all chains of any table, deletes any user-customized rule, chain and resets all packet counters on any rule left.<\/p>\n<h3>BASE_RULE_SET<\/h3>\n<p>Creates a minimal firewall setup with a new set of default configurations like <em>BLOCK<\/em>, <em>ANTI-FLOOD<\/em>, <em>ICMP<\/em>, <em>USER-IN<\/em> &amp; <em>USER-OUT<\/em> chains which are wired by the <em>iptables<\/em> standard chains. Most of these are reentrant and other calls may use them too to keep the footprint small. Access to local loopback (lo) is allowed. <em>New<\/em> packets are allowed to leave and <em>related<\/em> and <em>established<\/em> connections are allowed to return. Any invalid packet is blocked. Most <em>ICMP<\/em> types are allowed except the dangerous ones. <em>Syn-flooding<\/em> and <em>port scanners<\/em> are blocked by the <em>ANTI-FLOOD<\/em> chain and as a security measure (to avoid locking out yourself) <em>ssh<\/em> is allowed. Custom rules can be configured in the <em>USER-(IN|OUT)<\/em> chains.<br \/>\nThe <em>FORWARD<\/em> chain is left empty but will be used when calling additional <strong>FORWARD_SUBNET<\/strong> or <strong>FORWARD_SUBNET_PROTECTIVE<\/strong> calls. <em>OUTPUT<\/em> allows local loopback and only new, related or established packets of any protocol to be sent but only after <em>USER-OUT<\/em> chain has been passed. Setting up a firewall with <strong>BASE_RULE_SET<\/strong> only without any proper additional rules will mostly end up in completely blocked traffic\u00a0as the default policy setting of <em>INPUT<\/em>. <em>OUTPUT<\/em> and <em>FORWARD<\/em> is set to <strong><em>DROP<\/em><\/strong>.<\/p>\n<div id=\"attachment_651\" style=\"width: 642px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_base_rule_set.jpg\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-651\" class=\"wp-image-651\" src=\"http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_base_rule_set.jpg\" alt=\"ipturntables_base_rule_set\" width=\"632\" height=\"426\" \/><\/a><p id=\"caption-attachment-651\" class=\"wp-caption-text\">Figure B: Structural overview of a base ruleset. Click to enlarge.<\/p><\/div>\n<p>All these chains are used by the <em>INPUT<\/em> or <em>OUTPUT<\/em> chain, to protect the router host. A closer look of a base rule set reveals:<\/p>\n<pre>Chain INPUT (policy DROP 27083 packets, 1419K bytes)\n\u00a0pkts bytes target\u00a0\u00a0\u00a0\u00a0 prot opt in\u00a0\u00a0\u00a0\u00a0 out\u00a0\u00a0\u00a0\u00a0 source\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 destination\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\n  ...   ... ACCEPT\u00a0\u00a0\u00a0\u00a0  all\u00a0 --\u00a0 lo\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\n  ...   ... ACCEPT\u00a0\u00a0\u00a0\u00a0  all\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0  state RELATED,ESTABLISHED\n  ...   ... ICMP\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0  icmp --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\n  ...   ... BLOCK\u00a0\u00a0\u00a0\u00a0\u00a0  all\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0  state INVALID\n  ...   ... ANTI-FLOOD\u00a0 tcp\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0  tcp flags:0x17\/0x02\n  ...   ... ANTI-FLOOD\u00a0 tcp\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0 tcp flags:0x17\/0x04\n  ...   ... LOCAL\u00a0\u00a0\u00a0\u00a0\u00a0  all\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\n  ...   ... USER-IN\u00a0\u00a0\u00a0  all\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0 \/* add your custom INPUT rules in the USER-IN chain! *\/\n  ...   ... LOG\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0  all\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0 limit: avg 8\/min burst 16 LOG flags 0 level 4 prefix \"[IN4-DROP] \"\n\nChain FORWARD (policy DROP 1338 packets, 168K bytes)\n\u00a0pkts bytes target\u00a0\u00a0\u00a0\u00a0 prot opt in\u00a0\u00a0\u00a0\u00a0 out\u00a0\u00a0\u00a0\u00a0 source\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 destination\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\n  ...   ... LOG\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0  all\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0  limit: avg 8\/min burst 16 LOG flags 0 level 4 prefix \"[FW4-DROP] \"\n\nChain OUTPUT (policy DROP 2 packets, 80 bytes)\n\u00a0pkts bytes target\u00a0\u00a0\u00a0\u00a0 prot opt in\u00a0\u00a0\u00a0\u00a0 out\u00a0\u00a0\u00a0\u00a0 source\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 destination\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\n  ...   ... ACCEPT\u00a0\u00a0\u00a0\u00a0  all\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 lo\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\n  ...   ... ACCEPT\u00a0\u00a0\u00a0\u00a0  all\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0  state RELATED,ESTABLISHED\n  ...   ... USER-OUT\u00a0\u00a0  all\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0  \/* add your custom OUTPUT rules in the USER-OUT chain! *\/\n  ...   ... ACCEPT\u00a0\u00a0\u00a0\u00a0  all\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0  state NEW\n  ...   ... LOG\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0  all\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0  limit: avg 8\/min burst 16 LOG flags 0 level 4 prefix \"[OU4-DROP] \"<\/pre>\n<p>Notice that any of the default chains will log only some of the dropped packets to avoid flooding the logs with useless information. Any explicitly allowed packet won&#8217;t be logged the remaining dropped packets are still sufficient to give precious information about a pattern of an attack.<br \/>\nThis optimized order of rules carries a fragile structure which breaks easily when modified inappropriately, for that reason the <em>INPUT<\/em> chains calls at last the <em>USER-IN<\/em> chain likewise the <em>OUTPUT<\/em> chains has a <em>USER-OUT<\/em> chain for user customized rules.<\/p>\n<p>Some chains can be used in multiple scenarios because they aren&#8217;t limited to a protocol or port eg. the <em>ANTI-FLOOD<\/em> chain just consists of:<\/p>\n<pre>Chain ANTI-FLOOD (5 references)\n\u00a0pkts bytes target\u00a0\u00a0\u00a0\u00a0 prot opt in\u00a0\u00a0\u00a0\u00a0 out\u00a0\u00a0\u00a0\u00a0 source\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 destination\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\n  ...   ... RETURN\u00a0\u00a0\u00a0\u00a0 all\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 limit: avg 2\/sec burst 5\n  ...   ... LOG\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 all\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 LOG flags 0 level 4 prefix \"[BLOCK] (ANTIFLOOD) \"\n  ...   ... DROP\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 all\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0<\/pre>\n<p>First it checks if the time frame limit has been exceeded. If yes it&#8217;s considered as packet flooding and will be logged and finally dropped. If not it just returns. A rule can limit the call of <em>ANTI-FLOOD<\/em> by giving a precise filter criteria like <em>tcp flags<\/em> of 0x17\/0x02 (syn-flood protection) or 0x17\/0x04 (furtive port scanner) which can be found in the <em>INPUT<\/em> chain. Another example is the <em>ICMP<\/em> chain where <em>ANTI-FLOOD<\/em> is called to reduce <em>echo-request<\/em> packets.<\/p>\n<h4>Logging<\/h4>\n<p>Notice the <em>LOG<\/em> statement at the end of the <em>ANTI-FLOOD<\/em> chain which gives useful information about forwarded traffic which isn&#8217;t allowed!<br \/>\nThe <em>INPUT<\/em>, <em>OUTPUT<\/em>, <em>FORWARD<\/em> and <em>BLOCK<\/em> chains also log unwanted packets. This is the default as it helps to detect different attack patterns when any blocked packet is logged but on the other hand it can result in a talkative log.<br \/>\nThe <em>BLOCK<\/em> chain is called for any <span style=\"text-decoration: underline;\">known<\/span> unwanted packet (eg: invalid packets) but <em>ANTIFLOOD<\/em> is an exception as it uses a different log prefix to be able to distinguish the chain the packet got dropped at. Removing the <em>LOG<\/em> statements on these will reduce log size and just unknown packets on <em>INPUT<\/em>, <em>OUTPUT<\/em> and <em>FORWARD<\/em> will be logged but can make diagnostics harder when not any packet blocked is shown. So removing <em>LOG<\/em> statements is only recommended when your firewall setup has proofed to be rock solid but the logged packets on the default chains shouldn&#8217;t be removed anyway as they can give a good indication about still unknown attack scenarios or for traffic that got blocked unintended therefore the log prefixes for the standard chains differ from those intended to be blocked.<br \/>\nFor the standard chains they look like <em>IN(4|6)-DROP<\/em>, <em>OU(4|6)-DROP<\/em> and <em>FW(4|6)-DROP<\/em> and they are only reached if the packet passed <span style=\"text-decoration: underline;\">any<\/span> chain and there was no explicit rule available to allow the packet. Here&#8217;s an example of a log output in which it&#8217;s easy to distinguish among intended packet drops and those which just fall through and get dropped at the end:<\/p>\n<pre>... router kernel: [...] <span style=\"color: #ff0000;\">[BLOCK]<\/span> (INVALID) IN=eth2 OUT= MAC=... SRC=... DST=... LEN=40 TOS=0x00 PREC=0x00 TTL=57 ID=5170 PROTO=TCP SPT=443 DPT=43581 WINDOW=0 RES=0x00 RST URGP=0 \n... router kernel: [...] <span style=\"color: #ff6600;\">[IN4-DROP]<\/span> IN=eth2 OUT= MAC=... SRC=... DST=... LEN=40 TOS=0x00 PREC=0x00 TTL=46 ID=1396 PROTO=TCP SPT=37915 DPT=23 WINDOW=34315 RES=0x00 SYN URGP=0 \n... router kernel: [...] <span style=\"color: #ff6600;\">[IN4-DROP]<\/span> IN=eth2 OUT= MAC=... SRC=... DST=... LEN=40 TOS=0x00 PREC=0x00 TTL=242 ID=13673 PROTO=TCP SPT=59874 DPT=10778 WINDOW=1024 RES=0x00 SYN URGP=0 \n... router kernel: [...] <span style=\"color: #ff6600;\">[IN4-DROP]<\/span> IN=eth2 OUT= MAC=... SRC=... DST=... LEN=40 TOS=0x00 PREC=0x00 TTL=109 ID=256 PROTO=TCP SPT=77 DPT=8088 WINDOW=16384 RES=0x00 SYN URGP=0 \n... router kernel: [...] <span style=\"color: #ff6600;\">[IN4-DROP]<\/span> IN=eth2 OUT= MAC=... SRC=... DST=... LEN=40 TOS=0x00 PREC=0x00 TTL=239 ID=12533 PROTO=TCP SPT=60259 DPT=23 WINDOW=14600 RES=0x00 SYN URGP=0 \n... router kernel: [...] <span style=\"color: #ff0000;\">[BLOCK]<\/span> (INVALID) IN=eth2 OUT= MAC=... SRC=... DST=... LEN=40 TOS=0x00 PREC=0x00 TTL=46 ID=41048 DF PROTO=TCP SPT=22416 DPT=22 WINDOW=0 RES=0x00 RST URGP=0 \n... router kernel: [...] <span style=\"color: #ff0000;\">[BLOCK]<\/span> (INVALID) IN=eth2 OUT= MAC=... SRC=... DST=... LEN=40 TOS=0x00 PREC=0x00 TTL=46 ID=41055 DF PROTO=TCP SPT=22416 DPT=22 WINDOW=0 RES=0x00 RST URGP=0 \n... router kernel: [...] <span style=\"color: #ff6600;\">[IN4-DROP]<\/span> IN=eth2 OUT= MAC=... SRC=... DST=... LEN=40 TOS=0x00 PREC=0x00 TTL=43 ID=18744 PROTO=TCP SPT=35002 DPT=7547 WINDOW=57567 RES=0x00 SYN URGP=0 \n... router kernel: [...] <span style=\"color: #ff6600;\">[IN4-DROP]<\/span> IN=eth2 OUT= MAC=... SRC=... DST=... LEN=40 TOS=0x00 PREC=0x00 TTL=48 ID=1220 PROTO=TCP SPT=18156 DPT=23 WINDOW=56738 RES=0x00 SYN URGP=0 \n... router kernel: [...] <span style=\"color: #ff6600;\">[IN4-DROP]<\/span> IN=eth2 OUT= MAC=... SRC=... DST=... LEN=44 TOS=0x00 PREC=0x00 TTL=45 ID=18329 PROTO=TCP SPT=20562 DPT=23 WINDOW=33178 RES=0x00 SYN URGP=0 \n... router kernel: [...] <span style=\"color: #ff6600;\">[IN4-DROP]<\/span> IN=eth2 OUT= MAC=... SRC=... DST=... LEN=40 TOS=0x00 PREC=0x00 TTL=45 ID=64405 PROTO=TCP SPT=43383 DPT=23 WINDOW=55047 RES=0x00 SYN URGP=0 \n... router kernel: [...] <span style=\"color: #ff6600;\">[IN4-DROP]<\/span> IN=eth2 OUT= MAC=... SRC=... DST=... LEN=40 TOS=0x00 PREC=0x00 TTL=43 ID=47391 PROTO=TCP SPT=63184 DPT=23 WINDOW=60872 RES=0x00 SYN URGP=0 \n... router kernel: [...] <span style=\"color: #ff6600;\">[IN4-DROP]<\/span> IN=eth2 OUT= MAC=... SRC=... DST=... LEN=40 TOS=0x00 PREC=0x00 TTL=108 ID=256 PROTO=TCP SPT=77 DPT=3128 WINDOW=16384 RES=0x00 SYN URGP=0 \n... router kernel: [...] <span style=\"color: #ff0000;\">[BLOCK]<\/span> (INVALID) IN=eth2 OUT= MAC=... SRC=... DST=... LEN=40 TOS=0x00 PREC=0x00 TTL=55 ID=29709 PROTO=TCP SPT=443 DPT=47359 WINDOW=0 RES=0x00 RST URGP=0 \n... router kernel: [...] <span style=\"color: #ff0000;\">[BLOCK]<\/span> (INVALID) IN=eth2 OUT= MAC=... SRC=... DST=... LEN=40 TOS=0x00 PREC=0x00 TTL=55 ID=29711 PROTO=TCP SPT=443 DPT=47359 WINDOW=0 RES=0x00 RST URGP=0 \n... router kernel: [...] <span style=\"color: #ff0000;\">[BLOCK]<\/span> (INVALID) IN=eth2 OUT= MAC=... SRC=... DST=... LEN=40 TOS=0x00 PREC=0x00 TTL=55 ID=29712 PROTO=TCP SPT=443 DPT=47359 WINDOW=0 RES=0x00 RST URGP=0 \n... router kernel: [...] <span style=\"color: #ff6600;\">[IN4-DROP]<\/span> IN=eth2 OUT= MAC=... SRC=... DST=... LEN=40 TOS=0x00 PREC=0x00 TTL=43 ID=47391 PROTO=TCP SPT=63184 DPT=23 WINDOW=60872 RES=0x00 SYN URGP=0 \n... router kernel: [...] <span style=\"color: #ff6600;\">[IN4-DROP]<\/span> IN=eth2 OUT= MAC=... SRC=... DST=... LEN=40 TOS=0x00 PREC=0x00 TTL=243 ID=54321 PROTO=TCP SPT=40154 DPT=1099 WINDOW=65535 RES=0x00 SYN URGP=0<\/pre>\n<p><!--nextpage--><\/p>\n<h3>ALLOW_SUBNETS<\/h3>\n<p>The next step is to allow explicitly our subnets to talk to the router only. Let&#8217;s assume the router&#8217;s <em>IP<\/em> is configured to a class <em>C<\/em> private subnet like <em>192.168.1.1\/16<\/em> and all hosts on the <em>eth0<\/em> link should be allowed to send and receive traffic.<\/p>\n<pre>1: eth0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc pfifo_fast state UP group default qlen 1000\n link\/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff\n inet 192.168.1.1\/16 brd 192.168.255.255 scope global eth0\n valid_lft forever preferred_lft forever<\/pre>\n<p>Usally configuring a firewall by hand all the micro management stuff begins now by adding them to the <em>USER-IN<\/em> or <em>USER-OUT<\/em> chains but there&#8217;s an easier way. In a common network setup there&#8217;s often some kind of internal interface on which private subnets reside. The <strong>ALLOW_SUBNETS<\/strong> call just expects an interface name and all subnets configured on that interface will be allowed to talk to the router host by placing appropriate rules in:<\/p>\n<pre>Chain USER-IN (1 references)\n\u00a0pkts bytes target\u00a0\u00a0\u00a0\u00a0 prot opt in\u00a0\u00a0\u00a0\u00a0 out\u00a0\u00a0\u00a0\u00a0 source\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 destination\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\n\u00a0 ...\u00a0\u00a0 ... ACCEPT\u00a0\u00a0\u00a0\u00a0 all\u00a0 --\u00a0 eth0\u00a0\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 192.168.0.0\/16\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/* ALLOW_SUBNETS_0x50e549399da8 *\/\n\nChain USER-OUT (1 references)\n\u00a0pkts bytes target\u00a0\u00a0\u00a0\u00a0 prot opt in\u00a0\u00a0\u00a0\u00a0 out\u00a0\u00a0\u00a0\u00a0 source\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 destination\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\n  ...\u00a0\u00a0 ... ACCEPT\u00a0\u00a0\u00a0\u00a0 all\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 eth0\u00a0\u00a0\u00a0 192.168.1.1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 192.168.0.0\/16\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/* ALLOW_SUBNETS_0x50e549399da8 *\/<\/pre>\n<p>Notice the comments to the right which are used to identify these rules as rules created by an <strong>ALLOW_SUBNET<\/strong> call. This is a good example of a logical ruleset spanning over multiple chains.<\/p>\n<p>Although these rules allow primary traffic among the router and hosts of the <em>192.168.0.0\/16<\/em> subnet additional traffic is still not allowed like <em>link-local<\/em>, <em>service discovery<\/em> or <em>UPNP<\/em> which needs to be explicitly allowed by using <strong>ALLOW_LINK_LOCAL<\/strong> or <strong>ALLOW_SERVICE_DISCOVERY<\/strong> which in turn opens up traffic originating from <em>169.254.0.0\/16<\/em> or <em>fe80::\/10<\/em> subnets to allow use of <em>ZeroConf<\/em> address assignment like <em>IPv4ll<\/em> or <em>Netbios<\/em>|<em>DNS<\/em> based service discovery via <em>multicast<\/em> or <em>UPNP<\/em> features like available <em>DLNA<\/em> or <em>AirPlay<\/em> servers in your subnet. All these comfort features eases life on an internal link in a private subnet but these shouldn&#8217;t be available on a <em>WAN<\/em> device as they expose attack surface but since we&#8217;re on an internal link in our scenario we can safely allow them as <em>ipturntables.sh<\/em> in it&#8217;s default configuration doesn&#8217;t allow any forwarding of such traffic. Usally a router shouldn&#8217;t be allowed to use service discovery but there can be useful situations eg. when the router offers <em>DNS<\/em> multicast for hostname resolution on auto-configured subnets to specific interfaces only especially when a <em>DHCP<\/em> server isn&#8217;t available there.<\/p>\n<div id=\"attachment_665\" style=\"width: 641px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_allow_subnets.jpg\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-665\" class=\"alignnone wp-image-687\" src=\"https:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_allow_subnets-300x195.jpg\" alt=\"ipturntables_allow_subnets\" width=\"631\" height=\"410\" srcset=\"http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_allow_subnets-300x195.jpg 300w, http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_allow_subnets-768x500.jpg 768w, http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_allow_subnets-1024x667.jpg 1024w, http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_allow_subnets-624x406.jpg 624w, http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_allow_subnets.jpg 1461w\" sizes=\"auto, (max-width: 631px) 100vw, 631px\" \/><\/a><p id=\"caption-attachment-665\" class=\"wp-caption-text\">Figure C: Allowing a subnet, link-local and service discovery on a specific interface. Click to enlarge.<\/p><\/div>\n<p><!--nextpage--><\/p>\n<h3>FORWARD_SUBNET<\/h3>\n<p>Once some subnets are able to talk to the router things get interesting especially when to decide which subnet is allowed to reach each other or allowed to access services on the router.<br \/>\nLet&#8217;s say we have another private class <em>A<\/em> subnet (<em>10.0.0.0\/8<\/em>) connected to the router. Hosts from that subnet on <em>eth1<\/em> should be able to connect to hosts on the subnet (<em>192.168.0.0\/16<\/em>) on <em>eth0<\/em> interface <span style=\"text-decoration: underline;\">without<\/span> access to services running on the router itself <em>!<\/em><br \/>\nSince the router wouldn&#8217;t talk to anyone it explicitly knows, we need to configure an IP address (<em>10.1.1.1<\/em>) on the <em>eth1<\/em> interface to have a route from the subnet to be physically reachable <span style=\"text-decoration: underline;\">but<\/span> without allowing the subnet in the firewall. This time we won&#8217;t use a makefile but allow forwarding temporarily eg:<\/p>\n<pre>me@host:~# ipturntables.sh -4 FORWARD_SUBNET 10.0.0.0\/8 eth0\n# forwarding 10.0.0.0\/8 (eth1) to eth0.<\/pre>\n<p>The <strong>FORWARD_SUBNET<\/strong> call doesn&#8217;t take any protection measures and is therefore recommended only for forwarding internal subnets on different interfaces where protection isn&#8217;t needed. We also omit <em>service discovery<\/em>, <em>UPNP<\/em> or <em>link-local<\/em> traffic. When only <strong>FORWARD_SUBNET<\/strong> call is given it would just allow hosts from the class <em>A<\/em> subnet on <em>eth1<\/em> to pass the interface barrier by forwarding to the <em>eth0<\/em> interface <span style=\"text-decoration: underline;\">but<\/span> without having access to <em>service discovery<\/em>, <em>UPNP<\/em> or <em>link-local<\/em> since this traffic still can&#8217;t pass when going through different interfaces and would need an explicit <strong>ALLOW_SUBNET<\/strong> on the router&#8217;s interface.<\/p>\n<pre>Chain FORWARD (policy DROP 0 packets, 0 bytes)\n pkts bytes target     prot opt in     out     source        destination         \n    0     0 ACCEPT     all  --  eth0   eth1    0.0.0.0\/0     <span style=\"color: #008000;\">10.0.0.0\/8<\/span>          state NEW \/* FORWARD_SUBNET 10.1.1.0\/24 on 0x000e0c35edae to eth0 *\/\n    0     0 ACCEPT     all  --  eth0   eth1    0.0.0.0\/0     <span style=\"color: #008000;\">10.0.0.0\/8<\/span>          state RELATED,ESTABLISHED \/* FORWARD_SUBNET 10.1.1.0\/24 on 0x000e0c35edae to eth0 *\/\n    0     0 ACCEPT     all  --  eth1   eth0    <span style=\"color: #008000;\">10.0.0.0\/8<\/span>    0.0.0.0\/0            \/* FORWARD_SUBNET 10.1.1.0\/24 on 0x000e0c35edae to eth0 *\/\n 2555  319K LOG        all  --  *      *       0.0.0.0\/0     0.0.0.0\/0            limit: avg 8\/min burst 16 LOG flags 0 level 4 prefix \"[FW4-DROP] \"<\/pre>\n<p>Even when there would be other subnets (eg. <em>10.10.10.0\/8<\/em>) configured on <em>eth1<\/em> they would end up denied because <strong>FORWARD_SUBNET<\/strong> explicitly accepts only traffic from the specified subnet and only between the given interfaces they reside on although traffic originating from the class <em>A<\/em> subnet can be addressed anywhere it&#8217;s limited to subnets on the <em>eth0<\/em> interface only which is in our case the class <em>C<\/em> subnet.<\/p>\n<div id=\"attachment_699\" style=\"width: 640px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_forward_subnet.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-699\" class=\"wp-image-699\" src=\"https:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_forward_subnet-300x195.jpg\" alt=\"ipturntables_forward_subnet\" width=\"630\" height=\"410\" srcset=\"http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_forward_subnet-300x195.jpg 300w, http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_forward_subnet-768x499.jpg 768w, http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_forward_subnet-1024x665.jpg 1024w, http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_forward_subnet-624x405.jpg 624w, http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_forward_subnet.jpg 1461w\" sizes=\"auto, (max-width: 630px) 100vw, 630px\" \/><\/a><p id=\"caption-attachment-699\" class=\"wp-caption-text\">Figure D: Another private subnet which is forwarded internally only without allowing access to services on the router.<\/p><\/div>\n<p><!--nextpage--><\/p>\n<h3>Setting up a WAN device<\/h3>\n<p>Now here&#8217;s an example using dynamic configuration when the router sets up a connection to the outer world by using a <em>WAN<\/em> link on <em>eth2<\/em> interface may it be be either a cable modem or a <em>PPP<\/em> connection. Let&#8217;s assume a cable modem which gets it&#8217;s public <em>IP<\/em> by <em>DHCP<\/em> negotiation and only the subnet on <em>eth0<\/em> should be able to connect to the internet. This time we use event hooks from <em>\/etc\/network\/interfaces<\/em> file eg:<\/p>\n<pre>iface eth2 inet dhcp\n  pre-up ipturntables.sh -4 ALLOW_DHCP_CLIENT eth2\n  post-up ipturntables.sh -4 \\\n    FORWARD_SUBNET_PROTECTIVE 192.168.1.0\/24 eth2 \\\n    POSTROUTING_MASQUERADE 192.168.1.0\/24 eth2<\/pre>\n<h4>ALLOW_DHCP_CLIENT<\/h4>\n<p>First we need to allow <em>DHCP<\/em> traffic but instead of allowing a whole subnet or <em>IP<\/em> we just allow <em>DHCP<\/em> packets in the pre-up event of <em>eth2<\/em> interface to be able to get an public <em>IP<\/em> from the provider before <em>eth2<\/em> is brought up.<\/p>\n<pre>Chain USER-IN (1 references)\n pkts bytes target     prot opt in     out  source          destination         \n  ...   ... ACCEPT     all  --  eth0   *    192.168.1.0\/24  0.0.0.0\/0            \/* ALLOW_SUBNETS_0x50e549399da8 *\/\n  ...   ... ACCEPT     all  --  eth0   *    0.0.0.0\/0       0.0.0.0\/0            PKTTYPE = broadcast \/* ALLOW_SUBNETS_0x50e549199da8 (broadcast) *\/\n  ...   ... ACCEPT     all  --  eth0   *    0.0.0.0\/0       169.254.0.0\/16       \/* ALLOW_LINK_LOCAL on 0x50e549199da8 *\/\n  ...   ... ACCEPT     udp  --  eth0   *    0.0.0.0\/0       224.0.0.251          udp dpt:5353 \/* ALLOW_SERVICE_DISCOVERY on 0x50e549199da8 (multicast mDNS) *\/\n  ...   ... ACCEPT     udp  --  eth0   *    0.0.0.0\/0       239.255.255.250      udp dpt:1900 \/* ALLOW_SERVICE_DISCOVERY on 0x50e549199da8 (multicast UPnP) *\/\n<span style=\"color: #008000;\">  ...   ... ACCEPT     udp  --  eth2   *    0.0.0.0         255.255.255.255      udp spt:68 dpt:67 \/* ALLOW_DHCP_CLIENT_on_0x000e0c6e43fc *\/\n  ...   ... ACCEPT     udp  --  eth2   *    0.0.0.0\/0       0.0.0.0\/0            udp spt:67 dpt:68 \/* ALLOW_DHCP_CLIENT_on_0x000e0c6e43fc (dhcp\/bootp) *\/<\/span><\/pre>\n<p>On the <em>USER-IN<\/em> chain we have two new rules\u00a0below which allow <em>DHCP<\/em> packets on the <em>eth2<\/em> interface. For allowing the subnet (<em>192.168.1.0\/16<\/em>) on <em>eth0<\/em> interface access to the <em>WAN<\/em> interface we need to forward packets from there but using <em>FORWARD_SUBNET<\/em> without any protective measure would be dangerous so we need a forward which filters the critical stuff like malicous packets from the up stream.<\/p>\n<h4>FORWARD_SUBNET_PROTECTIVE<\/h4>\n<p>For that <em>ipturntables.sh<\/em> offers the <strong>FORWARD_SUBNET_PROTECTIVE<\/strong> call which protects the subnet in the same way the router protects itself on the <em>INPUT<\/em> and <em>OUTPUT<\/em> chains but since this needs some complex rule logic which would clutter the <em>USER-IN<\/em> chain therefore <em>ipturntables.sh<\/em> rather allocates two new chains to be able to have custom rules when setup differs for each subnet otherwise allowing eg. a specific port would allow it for any subnet if these would use the same static chains which is not always desired. Here&#8217;s an example:<\/p>\n<pre>Chain A274D8BD-IN (1 references)\n\u00a0pkts bytes target\u00a0\u00a0\u00a0\u00a0  prot opt in\u00a0\u00a0\u00a0\u00a0 out\u00a0 source\u00a0\u00a0\u00a0\u00a0\u00a0 destination\n\u00a0 ...\u00a0\u00a0 ... ICMP\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0 icmp --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0 0.0.0.0\/0\n\u00a0 ...\u00a0\u00a0 ... BLOCK\u00a0\u00a0\u00a0 \u00a0\u00a0 all\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0 state INVALID\n\u00a0 ...\u00a0\u00a0 ... ANTI-FLOOD\u00a0 tcp\u00a0 --  *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0 tcp flags:0x17\/0x02\n\u00a0 ...\u00a0\u00a0 ... ANTI-FLOOD\u00a0 tcp\u00a0 --  *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0 tcp flags:0x17\/0x04\n  ...   ... ACCEPT      all  --  *      *    0.0.0.0\/0   0.0.0.0\/0    state RELATED,ESTABLISHED\n\nChain A274D8BD-OUT (1 references)\n\u00a0pkts bytes target\u00a0\u00a0\u00a0\u00a0 prot opt in\u00a0\u00a0\u00a0\u00a0 out \u00a0 source\u00a0\u00a0\u00a0\u00a0\u00a0 destination\n\u00a0 ...   ... ACCEPT\u00a0\u00a0\u00a0\u00a0 all\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0  0.0.0.0\/0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0 state RELATED,ESTABLISHED\n\u00a0 ...\u00a0\u00a0 ... ACCEPT\u00a0\u00a0\u00a0\u00a0 all\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0  0.0.0.0\/0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0 state NEW\n  ...\u00a0  ... ACCEPT\u00a0\u00a0\u00a0\u00a0 tcp\u00a0 --\u00a0 *\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0\u00a0  0.0.0.0\/0\u00a0\u00a0 0.0.0.0\/0\u00a0\u00a0\u00a0 tcp multiport dports 80,443<\/pre>\n<p>One chain for forwarding inbound and one for outbound traffic. These are called in the <em>FORWARD<\/em> chain:<\/p>\n<pre>Chain FORWARD (policy DROP 19 packets, 2100 bytes)\n pkts bytes target        prot opt in     out     source          destination         \n  ...   ... A274D8BD-OUT  all  --  eth0   eth2    192.168.1.0\/24  0.0.0.0\/0         \/* FORWARD_SUBNET_PROTECTIVE_eth0_C0A8010018_eth2 *\/\n  ...   ... A274D8BD-IN   all  --  eth2   eth0    0.0.0.0\/0       192.168.1.0\/24    \/* FORWARD_SUBNET_PROTECTIVE_eth0_C0A8010018_eth2 *\/\n  ...   ... LOG           all  --  *      *       0.0.0.0\/0       0.0.0.0\/0         limit: avg 8\/min burst 16 LOG flags 0 level 4 prefix \"[FW4-DROP] \"<\/pre>\n<p>Notice that the subnet on <em>eth1<\/em> (which is chained behind the subnet on <em>eth0<\/em>) would still be blocked by the firewall when packets are sent to leave through the <em>WAN<\/em> interface as that would need another explicit forwarding rule to be allowed.<\/p>\n<div id=\"attachment_708\" style=\"width: 632px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_forward_subnet_protective.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-708\" class=\"wp-image-708\" src=\"https:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_forward_subnet_protective-300x195.jpg\" alt=\"ipturntables_forward_subnet_protective\" width=\"622\" height=\"404\" srcset=\"http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_forward_subnet_protective-300x195.jpg 300w, http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_forward_subnet_protective-768x500.jpg 768w, http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_forward_subnet_protective-1024x667.jpg 1024w, http:\/\/3ronco.vahanus.net\/wp-content\/uploads\/sites\/8\/2016\/11\/ipturntables_forward_subnet_protective.jpg 1452w\" sizes=\"auto, (max-width: 622px) 100vw, 622px\" \/><\/a><p id=\"caption-attachment-708\" class=\"wp-caption-text\">Figure E: A WAN connection forwarding a subnet.<\/p><\/div>\n<h4>POSTROUTING_MASQUERADE<\/h4>\n<p>So since now we have a connection to the outer world and an appropriate forward rule for the subnet on <em>eth0<\/em> we just need to masquerade our <em>IPs<\/em> (<em>192.168.1.0\/24<\/em>) to appear with the <em>IP<\/em> of the <em>WAN<\/em> interface for a working router setup at least for <em>IPv4<\/em> protocols. Now let&#8217;s have closer look at the last call of the <em>post-up<\/em> event hook of the <em>WAN<\/em> interface:<\/p>\n<pre>iface eth2 inet dhcp\n  ...\n  post-up ipturntables.sh -4 \\\n    FORWARD_SUBNET_PROTECTIVE 192.168.1.0\/24 eth2 \\\n    <span style=\"color: #008000;\">POSTROUTING_MASQUERADE 192.168.1.0\/24 eth2<\/span><\/pre>\n<p>Where exactly that is done with the <strong>POSTROUTING_MASQUERADE<\/strong> call. It rewrites the source address of any host <em>IP<\/em> of the subnet from <em>eth0<\/em> when leaving through the <em>WAN<\/em> interface on the <em>eth2<\/em> interface. This differs from <em>IPv6<\/em> setups where <em>NAT<\/em> is avoided by design but wether source <em>IP<\/em> addresses of a subnet are <em>NAT<\/em>&#8216;ed or not the <strong>FORWARD_SUBNET_PROTECTIVE<\/strong> call can be used in the same way for <em>IPv6<\/em> subnets even without NAT as the nature of a stateful firewall of allowing new outbound traffic but only allowing related or established traffic in, protects the hosts behind the router the same way regardless of the source IP address being mangled or not!<br \/>\n<!--nextpage--><\/p>\n<h3>Cleaning up the mess<\/h3>\n<p>The approach of allowing traffic only on demand when an interface pops up needs a mechanism to remove rules and\/or\u00a0deallocate chains dynamically when an interface goes down. Let&#8217;s assume our <em>WAN<\/em> interface will go down temporarily now and then. Rules like <strong>FORWARD_SUBNET_PROTECTIVE<\/strong> and <strong>POSTROUTING_MASQUERADE<\/strong> would remain and open up a theoretical chance for an attacker (with physical access to eth2) to probe different attack scenarios. For this we want the firewall to be brought back from the state in Fig. E to the state shown in Fig. D, have a closer look on the comment columns of the <em>FORWARD<\/em> chain.<\/p>\n<pre>Chain FORWARD (policy DROP 19 packets, 2100 bytes)\n... target        prot opt in   out   source          destination         \n... A274D8BD-OUT  all  --  eth0 eth2  192.168.1.0\/24  0.0.0.0\/0      \/* <span style=\"color: #339966;\">FORWARD_SUBNET_PROTECTIVE_eth0_C0A8010018_eth2<\/span> *\/\n... A274D8BD-IN   all  --  eth2 eth0  0.0.0.0\/0       192.168.1.0\/24 \/* <span style=\"color: #339966;\">FORWARD_SUBNET_PROTECTIVE_eth0_C0A8010018_eth2<\/span> *<\/pre>\n<p>likewise for the POSTROUTING_MASQUERADE call:<\/p>\n<pre>Chain POSTROUTING (policy ACCEPT 225K packets, 24M bytes)\n... target       prot  opt in  out   source          destination\n... MASQUERADE   all   --  *   eth2  192.168.1.0\/24  0.0.0.0\/0   \/* <span style=\"color: #339966;\">POSTROUTING_MASQUERADE eth0_C0A8010018_eth2<\/span> *\/<\/pre>\n<p>The marked text in the comments of these <em>iptables<\/em> rules can be used as an identifier to remove any rule which belongs to a specific ipturntables call. These can be copied from the terminal and used in conjunction with the <strong>REMOVE_RULES<\/strong> call:<\/p>\n<pre>root@myHost:~# ipturntables.sh -4 REMOVE_RULES \"<span style=\"color: #339966;\">FORWARD_SUBNET_PROTECTIVE_eth0_C0A8010018_eth2<\/span>\"\n# Removing rules containing '<span style=\"color: #339966;\">FORWARD_SUBNET_PROTECTIVE_eth0_C0A8010018_eth2<\/span>' in: FORWARD...done\n# Deallocating orphaned chains: A274D8BD-IN, A274D8BD-OUT...done\n\nroot@myHost:~# ipturntables.sh -4 REMOVE_RULES \"<span style=\"color: #339966;\">POSTROUTING_MASQUERADE eth0_C0A8010018_eth2<\/span>\"\n# Removing rules containing '<span style=\"color: #339966;\">POSTROUTING_MASQUERADE eth0_C0A8010018_eth2<\/span>' in: POSTROUTING...done\n# Deallocating orphaned chains: done<\/pre>\n<p>Any rule found with the given filter ID string will be removed and any related (probably orphaned) chain will be deallocated without reseting the whole ruleset of <em>iptables<\/em>. These calls can be placed eg. in the <em>post-down<\/em> event of an <em>\/etc\/network\/interfaces<\/em> file.<\/p>\n<p>This is just a small overview of what <em>ipturntables.sh<\/em> is capable of but there are even more features like <strong>ALLOW_PORT<\/strong>, <strong>FORWARD_PORT<\/strong>, <strong>MAC_FILTER<\/strong>, <strong>ALLOW_TUNNEL<\/strong>. In the examples shown here mainly <em>IPv4<\/em> was used but most rules also work for <em>IPv6<\/em> protocol. Feel free to have a look at the <a href=\"https:\/\/gitlab.vahanus.com\/3ronco\/ipturntables\">source<\/a> yourself.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>turn|table, turn\u00b7ta\u00b7ble (t\u00fbrn t b l), \/\u02c8t\u0259\u02d0nte\u026ab(\u0259)l Definition of turntable in English: noun The circular horizontal rotating platform of a phonograph on which the record is placed. A phonograph exclusive of amplifying circuitry and speakers. (turntables) A set of two or more record decks connected to sound mixing equipment, used by a DJ: the two [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":760,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[39,25,40,24,29,41,26,27],"class_list":["post-248","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-bb","tag-administration","tag-bash","tag-firewall","tag-iptables","tag-linux","tag-netfilter","tag-networks","tag-router"],"_links":{"self":[{"href":"http:\/\/3ronco.vahanus.net\/index.php?rest_route=\/wp\/v2\/posts\/248","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/3ronco.vahanus.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/3ronco.vahanus.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/3ronco.vahanus.net\/index.php?rest_route=\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"http:\/\/3ronco.vahanus.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=248"}],"version-history":[{"count":128,"href":"http:\/\/3ronco.vahanus.net\/index.php?rest_route=\/wp\/v2\/posts\/248\/revisions"}],"predecessor-version":[{"id":929,"href":"http:\/\/3ronco.vahanus.net\/index.php?rest_route=\/wp\/v2\/posts\/248\/revisions\/929"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/3ronco.vahanus.net\/index.php?rest_route=\/wp\/v2\/media\/760"}],"wp:attachment":[{"href":"http:\/\/3ronco.vahanus.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=248"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/3ronco.vahanus.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=248"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/3ronco.vahanus.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=248"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}