Thursday, September 24, 2015

Linux Iptables: Block All Incoming Traffic But Allow SSH


This is very common scenario. You want to permit access to a remote machine only by SSH. You would like to block all incoming traffic to your system except ssh connection under Linux.

Add following rules to your iptables shell script:
/sbin/iptables
-A INPUT -p tcp --dport 22 -j ACCEPT
/sbin/iptables
-A OUTPUT -p tcp --sport 22 -j ACCEPT
 
First rule will accept incoming (INPUT) tcp connection on port 22 (ssh server) and second rule will send response of incoming ssh server to client (OUTPUT) from our ssh server source port 22.
However, iptables with kernel 2.4/2.6 provides very powerful facility to filter rule based upon different connection states such as established or new connection etc. Here is complete small script to do this task:
 
#!/bin/sh
#
My system IP/set ip address of
server
SERVER_IP="65.55.12.13"
#
Flushing all rules
iptables
-F
iptables
-X
#
Setting default filter policy
iptables
-P INPUT DROP
iptables
-P OUTPUT DROP
iptables
-P FORWARD DROP
#
Allow unlimited traffic on loopback
iptables
-A INPUT -i lo -j ACCEPT
iptables
-A OUTPUT -o lo -j ACCEPT
 
#
Allow incoming ssh only
iptables
-A INPUT -p tcp -s 0/0
-d $SERVER_IP --sport 513:65535
--dport 22 -m state --state
NEW,ESTABLISHED -j ACCEPT
iptables
-A OUTPUT -p tcp -s $SERVER_IP -d 0/0
--sport 22 --dport 513:65535
-m state --state ESTABLISHED -j ACCEPT
#
make sure nothing comes or goes
out of this box
iptables
-A INPUT -j DROP
iptables
-A OUTPUT -j DROP
This script is purely strict firewall. It only allows incoming ssh. No other incoming service or ping request or no outgoing service or request allowed. Incoming ssh connection can be either new or already established one and that is what specified by state rule '-m state --state NEW,ESTABLISHED'. Outgoing ssh connection state can be established only. By default this script allows everyone to ssh in by rule -s 0/0. If you want this access limited by IP or network address then replace -s 0/0 with IP address. For example allow incoming ssh from IP 202.54.1.20:
 
#
Allow incoming ssh only from IP
202.54.1.20
iptables
-A INPUT -p tcp -s 202.54.1.20 -d
$SERVER_IP --sport 513:65535
--dport 22 -m state --state
NEW,ESTABLISHED -j ACCEPT
iptables
-A OUTPUT -p tcp -s $SERVER_IP -d
202.54.1.20 --sport 22
--dport 513:65535
-m state --state ESTABLISHED -j ACCEPT

Linux Iptables allow or block ICMP ping request

The Internet Control Message Protocol (ICMP) has many messages that are identified by a "type" field. You need to use 0 and 8 ICMP code types.
=> Zero (0) is for echo-reply
=> Eight (8) is for echo-request.
To enable ICMP ping incoming client request use following iptables rule (you need to add following rules to script).
My default firewall policy is blocking everything.

Task: Enable or allow ICMP ping incoming client request

Rule to enable ICMP ping incoming client request ( assuming that default iptables policy is to drop all INPUT and OUTPUT packets)
SERVER_IP="202.54.10.20"
iptables
-A INPUT -p icmp --icmp-type 8 -s 0/0 -d $SERVER_IP -m state --state
NEW,ESTABLISHED,RELATED -j ACCEPT
iptables
-A OUTPUT -p icmp --icmp-type 0 -s $SERVER_IP -d 0/0 -m state --state
ESTABLISHED,RELATED -j ACCEPT

Task: Allow or enable outgoing ping request

To enable ICMP ping outgoing request use following iptables rule:
SERVER_IP="202.54.10.20"
iptables
-A OUTPUT -p icmp --icmp-type 8 -s $SERVER_IP -d 0/0 -m state --state
NEW,ESTABLISHED,RELATED -j ACCEPT
iptables
-A INPUT -p icmp --icmp-type 0 -s 0/0 -d $SERVER_IP -m state --state
ESTABLISHED,RELATED -j ACCEPT

How do I disable outgoing ICMP request?

Use the following rules:
iptables
-A OUTPUT -p icmp --icmp-type echo-request -j DROP
OR
iptables
-A OUTPUT -p icmp --icmp-type 8 -j DROP
ICMP echo-request type will be block by above rule.
See ICMP TYPE NUMBERS (type fields). You can also get list of ICMP types, just type following command at shell prompt:# /sbin/iptables -p icmp -h

Linux Iptables: HowTo Block or Open HTTP/Web Service Port 80 & 443

By default Apache webserver listen on port 80 (http) and port 443 (https i.e. secure http). Apache webserver uses the TCP protocol to transfer information/data between server and browser. The default Iptables configuration does not allow inbound access to the HTTP (80) and HTTPS (443) ports used by the web server. This post explains how to allow inbound and outbound access to web services under Linux.

You can edit 
/etc/sysconfig/iptables file under RHEL / CentOS / Fedora Linux. Add the following lines, ensuring that they appear before the final LOG and DROP lines for the RH-Firewall-1-INPUT chain to open port 80 and 443:
 
-A
RH-Firewall-1-INPUT -m state --state NEW
-p tcp --dport 80 -j ACCEPT
-A
RH-Firewall-1-INPUT -m state --state NEW
-p tcp --dport 443 -j ACCEPT
 
Finally, restart the firewall:# service iptables restart
If you've your own shell script, try:
 
/sbin/iptables
-A INPUT -m state --state NEW -p tcp --dport 80
-j ACCEPT
/sbin/iptables
-A INPUT -m state --state NEW -p tcp --dport 443
-j ACCEPT
 

Allow incoming http/web traffic at port 80

 
SERVER_IP="202.54.10.20"
iptables
-A INPUT -p tcp -s 0/0
--sport 1024:65535
-d $SERVER_IP --dport 80
-m state --state NEW,ESTABLISHED -j ACCEPT
iptables
-A OUTPUT -p tcp -s $SERVER_IP --sport
80 -d 0/0
--dport 1024:65535
-m state --state ESTABLISHED -j ACCEPT
 

Allow incoming https/secure web traffic at port 443

 
SERVER_IP="202.54.10.20"
iptables
-A INPUT -p tcp -s 0/0
--sport 1024:65535
-d $SERVER_IP --dport 443
-m state --state NEW,ESTABLISHED -j ACCEPT
iptables
-A OUTPUT -p tcp -s $SERVER_IP --sport
443 -d 0/0
--dport 1024:65535
-m state --state ESTABLISHED -j ACCEPT
 

Allow outgoing http/web service traffic to port 80

 
SERVER_IP="202.54.10.20"
iptables
-A OUTPUT -p tcp -s $SERVER_IP --sport
1024:65535
-d 0/0
--dport 80 -m state --state
NEW,ESTABLISHED -j ACCEPT
iptables
-A INPUT -p tcp -s 0/0
--sport 80 -d $SERVER_IP
--dport 1024:65535
-m state --state ESTABLISHED -j ACCEPT
 

Allow outgoing https/secure web service traffic to port 443

 
SERVER_IP="202.54.10.20"
iptables
-A OUTPUT -p tcp -s $SERVER_IP --sport
1024:65535
-d 0/0
--dport 443 -m state --state
NEW,ESTABLISHED -j ACCEPT
iptables
-A INPUT -p tcp -s 0/0
--sport 443 -d $SERVER_IP
--dport 1024:65535
-m state --state ESTABLISHED -j ACCEPT
 

===============================================

How do I build a Simple Linux Firewall for DSL/Dial-up connection?

If you're new to Linux, here's a simple firewall that can be setup in minutes. Especially those coming from a Windows background, often lost themselves while creating linux firewall.
This is the most common question asked by Linux newbies (noobs). How do I install a personal firewall on a standalone Desktop Linux computer. In other words "I wanna a simple firewall that allows or permits me to visit anything from my computer but it should block everything from outside world".
Well that is pretty easy first remember INPUT means incoming and OUTPUT means outgoing connection/access. With following little script and discussion you should able to setup your own firewall.

Step # 1: Default Firewall policy

Set up default access policy to drop all incoming traffic but allow all outgoing traffic. This will allow you to make unlimited outgoing connections from any port but not incoming traffic/ports are allowed.iptables -p INPUT DROP
iptables -p OUTPUT ACCEPT

Step # 2: Allow unlimited traffic from loopback (lo) device

iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -i lo -j ACCEPT

Step # 3: Setup connection oriented access

Some protocol such as a FTP, DNS queries and UDP traffic needs an established connection access. In other words you need to allow all related connection using iptables state modules.iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT

Step # 4: Drop everything else and log it

iptables -A INPUT -j LOG
iptables -A INPUT -j REJECT
But wait you cannot type all above commands at a shell command prompt. It is a good idea to create a script called fw.start as follows (copy and paste following script in fw.start file):
#!/bin/sh
#
A simple
iptables
-F
iptables
-X
iptables
-t nat -F
iptables
-t nat -X
iptables
-t mangle -F
iptables
-t mangle -X
modprobe
ip_conntrack
modprobe
ip_conntrack_ftp
#
Setting default filter policy
iptables
-P INPUT DROP
iptables
-P OUTPUT ACCEPT
#
Unlimited access to loop back
iptables
-A INPUT -i lo -j ACCEPT
iptables
-A OUTPUT -o lo -j ACCEPT
#
Allow UDP, DNS and Passive FTP
iptables
-A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
#
DROP everything and Log it
iptables
-A INPUT -j LOG
iptables
-A INPUT -j DROP
You can enhance your tiny firewall with
  • Create a script to stop a firewall
  • This is optional, if you wish to start a firewall automatically as soon as Debian Linux boots up use the instruction outlined here
  • Finally if you wanna open incoming ssh (port 22) or http (port 80) then insert following two rules before #DROP everything and Log it line in above script:
iptables -A INPUT -p tcp -i eth0 --dport 22 -m state --state NEW -j ACCEPT
iptables -A INPUT -p tcp -i eth0 --dport 80 -m state --state NEW -j ACCEPT

Easy to use Linux firewall programs/tools

  • GUI tools - firestarter :: A graphical interfaced Open Source firewall for Linux. (highly recommended for Linux desktop users)
  • IPCop Firewall and SmoothWall :: Setup a dedicated firewall box. (highly recommended for Linux server and LAN/WAN users)
======================================================================

Linux Iptables: How to specify a range of IP addresses or ports

How can I save time and script size by specifying a range of IP addresses or ports using iptables?
In old version of iptables IP address ranges are only valid in the nat table (see below for example). However newer version does support option that allows you to specify a range of IP addresses or ports for regular tables such as input.

Iptables set range of IP addresses

You need to use following options with match extensions (-m Ext).
iprange : This matches on a given arbitrary range of IPv4 addresses.
  • [!]--src-range ip-ip: Match source IP in the specified range.
  • [!]--dst-range ip-ip: Match destination IP in the specified range.

Syntax:

-m iprange --src-range IP-IP -j ACTION
-m iprange --dst-range IP-IP -j ACTION
For example, allow incoming request on a port 22 for source IP in the 192.168.1.100-192.168.1.200 range only. You need to add something as follows to your iptables script:
iptables
-A INPUT -p tcp --destination-port 22 -m iprange --src-range
192.168.1.100-192.168.1.200 -j ACCEPT  

Port range

if --protocol tcp (-p tcp) is specified, you can specify source port range with following syntax:
  • --source-port port:port
  • --sport port:port
And destination port range specification with following option :
  • --destination-port port:port
  • --dport port:port
For example block lock all incoming ssh access at port 22, for source port range 513:65535:
iptables
-A INPUT -p tcp -s 0/0 --sport 513:65535 -d 195.55.55.78 --dport 22
-m state --state NEW,ESTABLISHED -j DROP
On the other hand, just allow incoming ssh request with following port range:
iptables
-A INPUT -p tcp -s 0/0 -d 195.55.55.78 --sport 513:65535 --dport 22
-m state --state NEW,ESTABLISHED -j ACCEPT
iptables
-A OUTPUT -p tcp -s 195.55.55.78 -d 0/0 --sport 22 --dport 513:65535
-m state --state ESTABLISHED -j ACCEPT

NAT table - range option

If you are using NAT table use options --to-source and --to-destination. For example IP address range:
iptables
-t nat -A POSTROUTING -j SNAT --to-source 192.168.1.100-192.168.1.200
ALTERNATIVELY, try range of ports:
iptables
-t nat -A POSTROUTING -j SNAT --to-source 192.168.1.100:2000-3000

Linux Iptables block or open DNS / bind service port 53



The domain name service provided by BIND (named) software. It uses both UDP and TCP protocol and listen on port 53. DNS queries less than 512 bytes are transferred using UDP protocol and large queries are handled by TCP protocol such as zone transfer.
i) named/bind server – TCP/UDP port 53
ii)Client (browser, dig etc) – port > 1023

Allow outgoing DNS client request:

Following iptables rules can be added to your shell script.
SERVER_IP is your server ip address
DNS_SERVER stores the nameserver (DNS) IP address provided by ISP or your own name servers.
Following rules are useful when you run single web/smtp server or even DSL/LL/dialup Internet connections:
SERVER_IP="202.54.10.20"
DNS_SERVER="202.54.1.5
202.54.1.6"
for
ip in $DNS_SERVER
do
iptables
-A OUTPUT -p udp -s $SERVER_IP --sport 1024:65535 -d $ip --dport 53
-m state --state NEW,ESTABLISHED -j ACCEPT
iptables
-A INPUT -p udp -s $ip --sport 53 -d $SERVER_IP --dport 1024:65535 -m
state --state ESTABLISHED -j ACCEPT
iptables
-A OUTPUT-p tcp -s $SERVER_IP --sport 1024:65535 -d $ip --dport 53 -m
state --state NEW,ESTABLISHED -j ACCEPT
iptables
-A INPUT -p tcp -s $ip --sport 53 -d $SERVER_IP --dport 1024:65535 -m
state --state ESTABLISHED -j ACCEPT
done

(B) Allow incoming DNS request at port 53:

Use following rules only if you are protecting dedicated DNS server.
SERVER_IP is IP address where BIND(named) is listing on port 53 for incoming DNS queries.
Please note that here I'm not allowing TCP protocol as I don't have secondary DNS server to do zone transfer.
SERVER_IP="202.54.10.20"
iptables
-A INPUT -p udp -s 0/0 --sport 1024:65535 -d $SERVER_IP --dport 53 -m
state --state NEW,ESTABLISHED -j ACCEPT
iptables
-A OUTPUT -p udp -s $SERVER_IP --sport 53 -d 0/0 --dport 1024:65535
-m state --state ESTABLISHED -j ACCEPT
iptables
-A INPUT -p udp -s 0/0 --sport 53 -d $SERVER_IP --dport 53 -m state
--state NEW,ESTABLISHED -j ACCEPT
iptables
-A OUTPUT -p udp -s $SERVER_IP --sport 53 -d 0/0 --dport 53 -m state
--state ESTABLISHED -j ACCEPT
Please note if you have secondary server, add following rules to above rules so that secondary server can do zone transfer from primary DNS server:
DNS2_IP="202.54.10.2"
iptables
-A INPUT -p tcp -s $DNS2_IP --sport 1024:65535 -d $SERVER_IP --dport
53 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables
-A OUTPUT -p tcp -s $SERVER_IP --sport 53 -d $DNS2_IP --dport
1024:65535 -m state --state ESTABLISHED -j ACCEPT

==============================================

Linux Iptables Limit the number of incoming tcp connection / syn-flood attacks


A SYN flood is a form of denial-of-service attack in which an attacker sends a succession of SYN requests to a target's system. This is a well known type of attack and is generally not effective against modern networks. It works if a server allocates resources after receiving a SYN, but before it has received the ACK.
if Half-open connections bind resources on the server, it may be possible to take up all these resources by flooding the server with SYN messages. Syn flood is common attack and it can be block with following iptables rules:
iptables
-A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j RETURN
All incoming connection are allowed till limit is reached:
  • --limit 1/s: Maximum average matching rate in seconds
  • --limit-burst 3: Maximum initial number of packets to match
Open our iptables script, add the rules as follows:
#
Limit the number of incoming tcp connections
#
Interface 0 incoming syn-flood protection
iptables
-N syn_flood
iptables
-A INPUT -p tcp --syn -j syn_flood
iptables
-A syn_flood -m limit --limit 1/s --limit-burst 3 -j RETURN
iptables
-A syn_flood -j DROP
#Limiting
the incoming icmp ping request:
iptables
-A INPUT -p icmp -m limit --limit  1/s --limit-burst 1 -j ACCEPT
iptables
-A INPUT -p icmp -m limit --limit 1/s --limit-burst 1 -j LOG
--log-prefix PING-DROP:
iptables
-A INPUT -p icmp -j DROP
iptables
-A OUTPUT -p icmp -j ACCEPT
First rule will accept ping connections to 1 per second, with an initial burst of 1. If this level crossed it will log the packet with PING-DROP in /var/log/message file. Third rule will drop packet if it tries to cross this limit. Fourth and final rule will allow you to use the continue established ping request of existing connection.
Where,
  • ‐‐limit rate: Maximum average matching rate: specified as a number, with an optional ‘/second’, ‘/minute’, ‘/hour’, or ‘/day’ suffix; the default is 3/hour.
  • ‐‐limit‐burst number: Maximum initial number of packets to match: this number gets recharged by one every time the limit specified above is not reached, up to this number; the default is 5.
You need to adjust the –limit-rate and –limit-burst according to your network traffic and requirements.
Let us assume that you need to limit incoming connection to ssh server (port 22) no more than 10 connections in a 10 minute:
iptables
-I INPUT -p tcp -s 0/0 -d $SERVER_IP --sport 513:65535 --dport 22 -m
state --state NEW,ESTABLISHED -m recent --set -j ACCEPT
iptables
-I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update
--seconds 600 --hitcount 11 -j DROP
iptables
-A OUTPUT -p tcp -s $SERVER_IP -d 0/0 --sport 22 --dport 513:65535 -m
state --state ESTABLISHED -j ACCEPT
==================================================================================================
Linux Iptables: How to block or open mail server / SMTP protocol

SMTP is used to send mail. Sendmail, Qmail, Postfix, Exim etc all are used on Linux as mail server. Mail server uses the TCP port 25. Following two iptable rule allows incoming SMTP request on port 25 for server IP address 202.54.1.20 (open port 25):
iptables -A INPUT -p tcp -s 0/0 --sport 1024:65535 -d 202.54.1.20 --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp -s 202.54.1.20 --sport 25 -d 0/0 --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPT
In order to block port 25 simply use target REJECT instead of ACCEPT in above rules.
And following two iptables rules allows outgoing SMTP server request for server IP address 202.54.1.20:
iptables -A OUTPUT -p tcp -s 202.54.1.20 --sport 1024:65535 -d 0/0 --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp -s 0/0 --sport 25 -d 202.54.1.20 --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPT

===========================================

Linux Iptables open Bittorrent tcp ports 6881 to 6889


I already wrote about Linux command line bittorrent client. However, I received few more queries regarding firewall issues. Basically you need to open ports using iptables.
Bittorrent client by default uses tcp 6881 to 6889 ports only. In order to work with Bittorrent client you need to open these ports on firewall. Remember, if you are behind a firewall (hardware or software) you need to enable port forwarding to internal systems.

Scenario # 1: Windows or Linux desktop behind router firewall

Internet
->     Hardware Router    -> Your Linux Desktop

         with
port forwarding          Client

             enabled
You have router (ADSL/DSL/Cable modem+router) and you have already enabled port forwarding on router (open web browser > Open router web admin interface > Find port forwarding > Enable port forwarding for bittorent protocol). You also need to open port using following iptables rules on Linux desktop (open TCP port 6881 to 6999):
iptables
-A INPUT -p tcp --destination-port 6881:6999 -j ACCEPT
iptables
-A OUTPUT -p tcp --source-port 6881:6999 -j ACCEPT
Here is a complete sample firewall script:
#!/bin/sh
iptables
-F
iptables
-X
iptables
-t nat -F
iptables
-t nat -X
iptables
-t mangle -F
iptables
-t mangle -X
modprobe
ip_conntrack
modprobe
ip_conntrack_ftp
#
Setting default filter policy
iptables
-P INPUT DROP
iptables
-P OUTPUT ACCEPT
#
Unlimited access to loop back
iptables
-A INPUT -i lo -j ACCEPT
iptables
-A OUTPUT -o lo -j ACCEPT
#
Allow UDP, DNS and Passive FTP
iptables
-A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
#allow
bittorent incomming client request
iptables
-A INPUT -p tcp --destination-port 6881:6999 -j ACCEPT
#Uncomment
below to allow sshd incoming client request
#iptables
-A INPUT -p tcp -dport 22 -j ACCEPT
#
DROP everything and Log it
iptables
-A INPUT -j LOG
iptables
-A INPUT -j DROP

Scenario # 2

Internet
-> Linux computer Router  ->  Your Linux Desktop

        with
port forwarding      OR Windows XP client

        enabled
using IPTABLES       IP:192.168.1.2

          IP:192.168.1.254
Here you are using a Linux as software firewall and iptables as your NAT (firewall) for internal network (192.168.1.2). You need to enable port forwarding to a internal Linux desktop (may be Windows XP desktop) for BitTorrent client system. Add following two line of code to your existing NAT firewall script.
iptables
-t nat -A PREROUTING -p tcp --dport 6881:6889
-j
DNAT --to-destination 192.168.1.2
iptables
-A FORWARD -s 192.168.1.2 -p tcp --dport 6881:6889
-j
ACCEPT
======================================================================================

Linux Iptables allow LDAPS server incoming client request

Secure LDAP (LDAP over SSL) incoming client request service by default listen on TCP port 636 for queries. Following iptable rules allows incoming client request (open port TCP port 636) for server IP address 202.54.1.20 :iptables -A INPUT -p tcp -s 0/0 --sport 1024:65535 -d 202.54.1.20 --dport 636 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp -s 202.54.1.20 --sport 636 -d 0/0 --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPT
Restrict access to LDAPS database server from your network is essential, following iptables allows incoming LDAPS client request from IP address 202.54.1.0/24 network only:
iptables -A INPUT -p tcp -s 202.54.1.0/24 --sport 1024:65535 -d 202.54.1.20 --dport 636 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp -s 202.54.1.20 --sport 636 -d 202.54.1.0/24 --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPT


No comments:

Post a Comment

Linux Tables: Block All Incoming Traffic But Allow SSH

  This is very common scenario. You want to permit access to a remote machine only by SSH. You would like to block all incoming traffic to y...