{"id":7776,"date":"2018-11-23T12:07:42","date_gmt":"2018-11-23T04:07:42","guid":{"rendered":"http:\/\/rmohan.com\/?p=7776"},"modified":"2018-11-23T12:07:42","modified_gmt":"2018-11-23T04:07:42","slug":"iptables-tips-and-tricks","status":"publish","type":"post","link":"https:\/\/mohan.sg\/?p=7776","title":{"rendered":"iptables tips and tricks"},"content":{"rendered":"<h3 id=\"tip-1-take-a-backup-of-your-iptables-configuration-before-you-start-working-on-it.\">Tip #1: Take a backup of your iptables configuration before you start working on it.<\/h3>\n<p>Back up your configuration with the command:<\/p>\n<pre><span class=\"geshifilter\"><code class=\"text geshifilter-text\">\/sbin\/iptables-save &gt; \/root\/iptables-works<\/code><\/span><\/pre>\n<h3 id=\"tip-2-even-better-include-a-timestamp-in-the-filename\">Tip #2: Even better, include a timestamp in the filename.<\/h3>\n<p>Add the timestamp with the command:<\/p>\n<pre><span class=\"geshifilter\"><code class=\"text geshifilter-text\">\/sbin\/iptables-save &gt; \/root\/iptables-works-`date +%F`<\/code><\/span><\/pre>\n<p>You get a file with a name like:<\/p>\n<pre><span class=\"geshifilter\"><code class=\"text geshifilter-text\">\/root\/iptables-works-2018-09-11<\/code><\/span><\/pre>\n<p>If you do something that prevents your system from working, you can quickly restore it:<\/p>\n<pre><span class=\"geshifilter\"><code class=\"text geshifilter-text\">\/sbin\/iptables-restore &lt; \/root\/iptables-works-2018-09-11<\/code><\/span><\/pre>\n<h3 id=\"tip-3-every-time-you-create-a-backup-copy-of-the-iptables-policy-create-a-link-to-the-file-with-latest-in-the-name.\">Tip #3: Every time you create a backup copy of the iptables policy, create a link to the file with &#8216;latest&#8217; in the name.<\/h3>\n<pre><span class=\"geshifilter\"><code class=\"text geshifilter-text\">ln \u2013s \/root\/iptables-works-`date +%F` \/root\/iptables-works-latest<\/code><\/span><\/pre>\n<h3 id=\"tip-4-put-specific-rules-at-the-top-of-the-policy-and-generic-rules-at-the-bottom.\">Tip #4: Put specific rules at the top of the policy and generic rules at the bottom.<\/h3>\n<p>Avoid generic rules like this at the top of the policy rules:<\/p>\n<pre><span class=\"geshifilter\"><code class=\"text geshifilter-text\">iptables -A INPUT -p tcp --dport 22 -j DROP<\/code><\/span><\/pre>\n<p>The more criteria you specify in the rule, the less chance you will have of locking yourself out. Instead of the very generic rule above, use something like this:<\/p>\n<pre><span class=\"geshifilter\"><code class=\"text geshifilter-text\">iptables -A INPUT -p tcp --dport 22 \u2013s 10.0.0.0\/8 \u2013d 192.168.100.101 -j DROP<\/code><\/span><\/pre>\n<p>This rule appends (<strong>-A<\/strong>) to the\u00a0<strong>INPUT<\/strong>\u00a0chain a rule that will\u00a0<strong>DROP<\/strong>\u00a0any packets originating from the CIDR block\u00a0<strong>10.0.0.0\/8<\/strong>\u00a0on TCP (<strong>-p tcp<\/strong>) port 22 (<strong>&#8211;dport 22<\/strong>) destined for IP address 192.168.100.101 (<strong>-d 192.168.100.101<\/strong>).<\/p>\n<p>There are plenty of ways you can be more specific. For example, using\u00a0<strong>-i eth0<\/strong>\u00a0will limit the processing to a single NIC in your server. This way, the filtering actions will not apply the rule to\u00a0<strong>eth1<\/strong>.<\/p>\n<h3 id=\"tip-5-whitelist-your-ip-address-at-the-top-of-your-policy-rules.\">Tip #5: Whitelist your IP address at the top of your policy rules.<\/h3>\n<p>This is a very effective method of not locking yourself out. Everybody else, not so much.<\/p>\n<pre><span class=\"geshifilter\"><code class=\"text geshifilter-text\">iptables -I INPUT -s &lt;your IP&gt; -j ACCEPT<\/code><\/span><\/pre>\n<p>You need to put this as the\u00a0<em>first<\/em>\u00a0rule for it to work properly. Remember,\u00a0<strong>-I<\/strong>\u00a0inserts it as the first rule;\u00a0<strong>-A<\/strong>\u00a0appends it to the end of the list.<\/p>\n<h3 id=\"tip-6-know-and-understand-all-the-rules-in-your-current-policy.\">Tip #6: Know and understand all the rules in your current policy.<\/h3>\n<p>Not making a mistake in the first place is half the battle. If you understand the inner workings behind your iptables policy, it will make your life easier. Draw a flowchart if you must. Also remember: What the policy does and what it is supposed to do can be two different things.<\/p>\n<h2 id=\"set-up-a-workstation-firewall-policy\">Set up a workstation firewall policy<\/h2>\n<p>Scenario: You want to set up a workstation with a restrictive firewall policy.<\/p>\n<h3 id=\"tip-1-set-the-default-policy-as-drop.\">Tip #1: Set the default policy as DROP.<\/h3>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\"># Set a default policy of DROP<br \/>\n*filter<br \/>\n:INPUT DROP [0:0]<br \/>\n:FORWARD DROP [0:0]<br \/>\n:OUTPUT DROP [0:0]<\/div>\n<\/div>\n<h3 id=\"tip-2-allow-users-the-minimum-amount-of-services-needed-to-get-their-work-done.\">Tip #2: Allow users the minimum amount of services needed to get their work done.<\/h3>\n<p>The iptables rules need to allow the workstation to get an IP address, netmask, and other important information via DHCP (<strong>-p udp &#8211;dport 67:68 &#8211;sport 67:68<\/strong>). For remote management, the rules need to allow inbound SSH (<strong>&#8211;dport 22<\/strong>), outbound mail (<strong>&#8211;dport 25<\/strong>), DNS (<strong>&#8211;dport 53<\/strong>), outbound ping (<strong>-p icmp<\/strong>), Network Time Protocol (<strong>&#8211;dport 123 &#8211;sport 123<\/strong>), and outbound HTTP (<strong>&#8211;dport 80<\/strong>) and HTTPS (<strong>&#8211;dport 443<\/strong>).<\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\"># Set a default policy of DROP<br \/>\n*filter<br \/>\n:INPUT DROP [0:0]<br \/>\n:FORWARD DROP [0:0]<br \/>\n:OUTPUT DROP [0:0]<\/p>\n<p># Accept any related or established connections<br \/>\n-I INPUT \u00a01 -m state &#8211;state RELATED,ESTABLISHED -j ACCEPT<br \/>\n-I OUTPUT 1 -m state &#8211;state RELATED,ESTABLISHED -j ACCEPT<\/p>\n<p># Allow all traffic on the loopback interface<br \/>\n-A INPUT -i lo -j ACCEPT<br \/>\n-A OUTPUT -o lo -j ACCEPT<\/p>\n<p># Allow outbound DHCP request<br \/>\n-A OUTPUT \u2013o eth0 -p udp &#8211;dport 67:68 &#8211;sport 67:68 -j ACCEPT<\/p>\n<p># Allow inbound SSH<br \/>\n-A INPUT -i eth0 -p tcp -m tcp &#8211;dport 22 -m state &#8211;state NEW \u00a0-j ACCEPT<\/p>\n<p># Allow outbound email<br \/>\n-A OUTPUT -i eth0 -p tcp -m tcp &#8211;dport 25 -m state &#8211;state NEW \u00a0-j ACCEPT<\/p>\n<p># Outbound DNS lookups<br \/>\n-A OUTPUT -o eth0 -p udp -m udp &#8211;dport 53 -j ACCEPT<\/p>\n<p># Outbound PING requests<br \/>\n-A OUTPUT \u2013o eth0 -p icmp -j ACCEPT<\/p>\n<p># Outbound Network Time Protocol (NTP) requests<br \/>\n-A OUTPUT \u2013o eth0 -p udp &#8211;dport 123 &#8211;sport 123 -j ACCEPT<\/p>\n<p># Outbound HTTP<br \/>\n-A OUTPUT -o eth0 -p tcp -m tcp &#8211;dport 80 -m state &#8211;state NEW -j ACCEPT<br \/>\n-A OUTPUT -o eth0 -p tcp -m tcp &#8211;dport 443 -m state &#8211;state NEW -j ACCEPT<\/p>\n<p>COMMIT<\/p><\/div>\n<\/div>\n<h2 id=\"restrict-an-ip-address-range\">Restrict an IP address range<\/h2>\n<p>Scenario: The CEO of your company thinks the employees are spending too much time on Facebook and not getting any work done. The CEO tells the CIO to do something about the employees wasting time on Facebook. The CIO tells the CISO to do something about employees wasting time on Facebook. Eventually,\u00a0<em>you<\/em>\u00a0are told the employees are wasting too much time on Facebook, and you have to do something about it. You decide to block all access to Facebook. First, find out Facebook&#8217;s IP address by using the\u00a0<strong>host<\/strong>\u00a0and\u00a0<strong>whois<\/strong>\u00a0commands.<\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\">host -t a www.facebook.com<br \/>\nwww.facebook.com is an alias for star.c10r.facebook.com.<br \/>\nstar.c10r.facebook.com has address 31.13.65.17<br \/>\nwhois 31.13.65.17 | grep inetnum<br \/>\ninetnum: \u00a0 \u00a0 \u00a0 \u00a031.13.64.0 &#8211; 31.13.127.255<\/div>\n<\/div>\n<p>Then convert that range to CIDR notation by using the\u00a0<a href=\"http:\/\/www.ipaddressguide.com\/cidr\" target=\"_blank\" rel=\"noopener\">CIDR to IPv4 Conversion<\/a>\u00a0page. You get\u00a0<strong>31.13.64.0\/18<\/strong>. To prevent outgoing access to\u00a0<a href=\"http:\/\/www.facebook.com\/\" target=\"_blank\" rel=\"noopener\">www.facebook.com<\/a>, enter:<\/p>\n<pre><span class=\"geshifilter\"><code class=\"text geshifilter-text\">iptables -A OUTPUT -p tcp -i eth0 \u2013o eth1 \u2013d 31.13.64.0\/18 -j DROP<\/code><\/span><\/pre>\n<h2 id=\"regulate-by-time\">Regulate by time<\/h2>\n<p>Scenario: The backlash from the company&#8217;s employees over denying access to Facebook access causes the CEO to relent a little (that and his administrative assistant&#8217;s reminding him that she keeps HIS Facebook page up-to-date). The CEO decides to allow access to Facebook.com only at lunchtime (12PM to 1PM). Assuming the default policy is DROP, use iptables&#8217; time features to open up access.<\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\">iptables \u2013A OUTPUT -p tcp -m multiport &#8211;dport http,https -i eth0 -o eth1 -m time &#8211;timestart 12:00 &#8211;timestart 12:00 \u2013timestop 13:00 \u2013d<br \/>\n31.13.64.0\/18 \u00a0-j ACCEPT<\/div>\n<\/div>\n<p>This command sets the policy to allow (<strong>-j ACCEPT<\/strong>) http and https (<strong>-m multiport &#8211;dport http,https<\/strong>) between noon (<strong>&#8211;timestart 12:00<\/strong>) and 13PM (<strong>&#8211;timestop 13:00<\/strong>) to Facebook.com (<strong>\u2013d\u00a0<a href=\"http:\/\/31.13.64.0\/18\" target=\"_blank\" rel=\"noopener\" data-saferedirecturl=\"https:\/\/www.google.com\/url?q=http:\/\/31.13.64.0\/18&amp;source=gmail&amp;ust=1538232195843000&amp;usg=AFQjCNHpAg9-pKqjpdq1eqhd4rKakYDlFA\">31.13.64.0\/18<\/a><\/strong>).<\/p>\n<h2 id=\"regulate-by-time---take-2\">Regulate by time\u2014Take 2<\/h2>\n<p>Scenario: During planned downtime for system maintenance, you need to deny all TCP and UDP traffic between the hours of 2AM and 3AM so maintenance tasks won&#8217;t be disrupted by incoming traffic. This will take two iptables rules:<\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\">iptables -A INPUT -p tcp -m time &#8211;timestart 02:00 &#8211;timestop 03:00 -j DROP<br \/>\niptables -A INPUT -p udp -m time &#8211;timestart 02:00 &#8211;timestop 03:00 -j DROP<\/div>\n<\/div>\n<p>With these rules, TCP and UDP traffic (<strong>-p tcp and -p udp\u00a0<\/strong>) are denied (<strong>-j DROP<\/strong>) between the hours of 2AM (<strong>&#8211;timestart 02:00<\/strong>) and 3AM (<strong>&#8211;timestop 03:00<\/strong>) on input (<strong>-A INPUT<\/strong>).<\/p>\n<h2 id=\"limit-connections-with-iptables\">Limit connections with iptables<\/h2>\n<p>Scenario: Your internet-connected web servers are under attack by bad actors from around the world attempting to DoS (Denial of Service) them. To mitigate these attacks, you restrict the number of connections a single IP address can have to your web server:<\/p>\n<pre><span class=\"geshifilter\"><code class=\"text geshifilter-text\">iptables \u2013A INPUT \u2013p tcp \u2013syn -m multiport -\u2013dport http,https \u2013m connlimit -\u2013connlimit-above 20 \u2013j REJECT -\u2013reject-with-tcp-reset<\/code><\/span><\/pre>\n<p>Let&#8217;s look at what this rule does. If a host makes more than 20 (<strong>-\u2013connlimit-above 20<\/strong>) new connections (<strong>\u2013p tcp \u2013syn<\/strong>) in a minute to the web servers (<strong>-\u2013dport http,https<\/strong>), reject the new connection (<strong>\u2013j REJECT<\/strong>) and tell the connecting host you are rejecting the connection (<strong>-\u2013reject-with-tcp-reset<\/strong>).<\/p>\n<h2 id=\"monitor-iptables-rules\">Monitor iptables rules<\/h2>\n<p>Scenario: Since iptables operates on a &#8220;first match wins&#8221; basis as packets traverse the rules in a chain, frequently matched rules should be near the top of the policy and less frequently matched rules should be near the bottom. How do you know which rules are traversed the most or the least so they can be ordered nearer the top or the bottom?<\/p>\n<h3 id=\"tip-1-see-how-many-times-each-rule-has-been-hit.\">Tip #1: See how many times each rule has been hit.<\/h3>\n<p>Use this command:<\/p>\n<pre><span class=\"geshifilter\"><code class=\"text geshifilter-text\">iptables -L -v -n \u2013line-numbers<\/code><\/span><\/pre>\n<p>The command will list all the rules in the chain (<strong>-L<\/strong>). Since no chain was specified, all the chains will be listed with verbose output (<strong>-v<\/strong>) showing packet and byte counters in numeric format (<strong>-n<\/strong>) with line numbers at the beginning of each rule corresponding to that rule&#8217;s position in the chain.<\/p>\n<p>Using the packet and bytes counts, you can order the most frequently traversed rules to the top and the least frequently traversed rules towards the bottom.<\/p>\n<h3 id=\"tip-2-remove-unnecessary-rules.\">Tip #2: Remove unnecessary rules.<\/h3>\n<p>Which rules aren&#8217;t getting any matches at all? These would be good candidates for removal from the policy. You can find that out with this command:<\/p>\n<pre><span class=\"geshifilter\"><code class=\"text geshifilter-text\">iptables -nvL | grep -v \"0 \u00a0 \u00a0 0\"<\/code><\/span><\/pre>\n<p>Note: that&#8217;s not a tab between the zeros; there are five spaces between the zeros.<\/p>\n<h3 id=\"tip-3-monitor-whats-going-on.\">Tip #3: Monitor what&#8217;s going on.<\/h3>\n<p>You would like to monitor what&#8217;s going on with iptables in real time, like with\u00a0<strong>top<\/strong>. Use this command to monitor the activity of iptables activity dynamically and show only the rules that are actively being traversed:<\/p>\n<pre><span class=\"geshifilter\"><code class=\"text geshifilter-text\">watch --interval=5 'iptables -nvL | grep -v \"0 \u00a0 \u00a0 0\"'<\/code><\/span><\/pre>\n<p><strong>watch<\/strong>\u00a0runs\u00a0<strong>&#8216;iptables -nvL | grep -v &#8220;0 \u00a0 \u00a0 0&#8243;&#8216;<\/strong>\u00a0every five seconds and displays the first screen of its output. This allows you to watch the packet and byte\u00a0counts change over time.<\/p>\n<h2 id=\"report-on-iptables\">Report on iptables<\/h2>\n<p>Scenario: Your manager thinks this iptables firewall stuff is just great, but a daily activity report would be even better. Sometimes it&#8217;s more important to write a report than to do the work.<\/p>\n<p>Use the\u00a0packet filter\/firewall\/IDS log analyzer\u00a0<a href=\"http:\/\/fwlogwatch.inside-security.de\/\" target=\"_blank\" rel=\"noopener\">FWLogwatch<\/a>\u00a0to create reports based on the iptables firewall logs. FWLogwatch supports many log formats and offers many analysis options. It generates daily and monthly summaries of the log files, allowing the security administrator to free up substantial time, maintain better control over network\u00a0security, and reduce unnoticed attacks.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Tip #1: Take a backup of your iptables configuration before you start working on it. <\/p>\n<p>Back up your configuration with the command:<\/p>\n<p> \/sbin\/iptables-save &gt; \/root\/iptables-works Tip #2: Even better, include a timestamp in the filename. <\/p>\n<p>Add the timestamp with the command:<\/p>\n<p> \/sbin\/iptables-save &gt; \/root\/iptables-works-`date +%F` <\/p>\n<p>You get a file with a name like:<\/p>\n<p> \/root\/iptables-works-2018-09-11 <\/p>\n<p>If [&#8230;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[73],"tags":[],"_links":{"self":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/7776"}],"collection":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7776"}],"version-history":[{"count":1,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/7776\/revisions"}],"predecessor-version":[{"id":7777,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/7776\/revisions\/7777"}],"wp:attachment":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7776"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7776"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7776"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}