# iptables - allow ping to the outside

## namron

I want to be able to allow ping from the inside of my firewall to the outside world, but drop it otherwise.  Dropping it is not the problem, that i've done.  However, I can't seem to enable it to be allowed through from my machine.

Any suggestions?

Thanks,

Namron

----------

## bakreule

This is what you're looking for:

```

#Change this accordingly

IPTABLES=/sbin/iptables

WAN_IFACE="eth0"

ANYWHERE="0/0"

# Iptables rules

$IPTABLES -A INPUT  -p icmp  --icmp-type echo-reply -s $ANYWHERE -i $WAN_IFACE -j ACCEPT

$IPTABLES -A INPUT  -p icmp  --icmp-type destination-unreachable -s $ANYWHERE -i $WAN_IFACE -j ACCEPT

$IPTABLES -A INPUT  -p icmp  --icmp-type time-exceeded -s $ANYWHERE -i $WAN_IFACE -j ACCEPT

```

The first line allows in echo replies, which are responses to your pings. The 2nd & 3rd lines allow in messages relating to problems with the network. Every other type of ICMP message (including, most importantly, ping requests) are dropped.

All this is assuming that by default the INPUT chain has a DROP policy and doesn't have some other rule above which supercedes this one. Before you run these lines in your iptables script you should have something along the lines of:

```

# Clear all the rules, start from scratch

$IPTABLES -F

# Set the default policies of the built-in chains. If no match for any

# of the rules below, these will be the defaults that IPTABLES uses.

$IPTABLES -P FORWARD DROP

$IPTABLES -P OUTPUT ACCEPT

$IPTABLES -P INPUT DROP

```

Good firewall rulesets normally start with these anyway.

----------

## adaptr

```
iptables -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT
```

NOTE that whether this works depends on what is in your other chains!

----------

## namron

Thanks for the reply.  That looks great, however I am having some trouble integrating that into my script.  It is probably having to do with my rules.  Here are my current icmp rules:

$IPTABLES -N icmp_allowed

$IPTABLES -F icmp_allowed

$IPTABLES -A icmp_allowed -m state --state NEW -p icmp --icmp-type time-exceeded -j ACCEPT

$IPTABLES -A icmp_allowed -m state --state NEW -p icmp --icmp-type destination-unreachable -j ACCEPT

$IPTABLES -A icmp_allowed -p icmp -j LOG --log-prefix "Bad ICMP traffic:"

$IPTABLES -A icmp_allowed -p icmp -j DROP

Where would your suggestion go in relation to these? Or do I even need these with your suggested rules?

Thanks,

Namron

----------

## bakreule

Why do you have the '-m state' in there? I could be wrong, but I thought ICMP packets were stateless, thus the -m option has no effect.

As far as your rules, they look fine. Just add the '--icmp-type echo-reply' line after the '-F icmp_allowed' line.

----------

## namron

I left in the "-m state" from the script that i found in the gentoo security guide.  I modified my script from one based on that one.

I'll try this and post a reply.

Thanks,

Namron

----------

## namron

I assumed that the state just was meant to match a new ping request.

----------

## namron

I'm still not getting out, "ping: sendmsg: Operation not permitted".  

Here is my script: (any suggestions appreciated, this is for a webserver by the way)

#!/sbin/runscript

IPTABLES=/sbin/iptables

IPTABLESSAVE=/sbin/iptables-save

IPTABLESRESTORE=/sbin/iptables-restore

FIREWALL=/etc/firewall.rules

DNS1=192.xxx.xxx.xxx

DNS2=192.xxx.xxx.xxx

IP=192.xxx.xxx.xxx

INTERFACE=eth0

LOOPBACK_INTERFACE=lo

ANYWHERE="0/0"

opts="${opts} showstatus panic save restore showoptions rules"

depend() {

  need net

}

rules() {

stop

ebegin "Setting internal rules"

einfo "Setting default rule to drop"

$IPTABLES -P FORWARD DROP

$IPTABLES -P INPUT   DROP

$IPTABLES -P OUTPUT  DROP

#default rule

einfo "Creating states chain"

$IPTABLES -N allowed-connection

$IPTABLES -F allowed-connection

$IPTABLES -A allowed-connection -m state --state ESTABLISHED,RELATED -j ACCEPT

$IPTABLES -A allowed-connection -i $INTERFACE -m limit -j LOG --log-prefix "Bad packet from ${INTERFACE}:"

$IPTABLES -A allowed-connection -j DROP

#ICMP traffic

einfo "Creating icmp chain"

$IPTABLES -N icmp_allowed

$IPTABLES -F icmp_allowed

$IPTABLES -A icmp_allowed -p icmp  --icmp-type echo-reply -s $ANYWHERE -i $INTERFACE -j ACCEPT

$IPTABLES -A icmp_allowed -m state --state NEW -p icmp --icmp-type time-exceeded -j ACCEPT

$IPTABLES -A icmp_allowed -m state --state NEW -p icmp --icmp-type destination-unreachable -j ACCEPT

$IPTABLES -A icmp_allowed -p icmp -j LOG --log-prefix "Bad ICMP traffic:"

$IPTABLES -A icmp_allowed -p icmp -j DROP

einfo "Creating outgoing dns traffic chain"

$IPTABLES -N allow-dns-traffic-out

$IPTABLES -F allow-dns-traffic-out

$IPTABLES -A allow-dns-traffic-out -p udp -d $DNS1 --dport domain -j ACCEPT

$IPTABLES -A allow-dns-traffic-out -p udp -d $DNS2 --dport domain -j ACCEPT

#Incoming traffic on http/https

einfo "Creating incoming http/https traffic chain"

$IPTABLES -N allow-www-traffic-in

$IPTABLES -F allow-www-traffic-in

#Flood protection

$IPTABLES -A allow-www-traffic-in -m limit --limit 1/second -p tcp --tcp-flags ALL RST --dport www -j ACCEPT

$IPTABLES -A allow-www-traffic-in -m limit --limit 1/second -p tcp --tcp-flags ALL FIN --dport www -j ACCEPT

$IPTABLES -A allow-www-traffic-in -m limit --limit 1/second -p tcp --tcp-flags ALL SYN --dport www -j ACCEPT

$IPTABLES -A allow-www-traffic-in -m state --state NEW,RELATED,ESTABLISHED -p tcp --dport www -j ACCEPT

$IPTABLES -A allow-www-traffic-in -m limit --limit 1/second -p tcp --tcp-flags ALL RST --dport https -j ACCEPT

$IPTABLES -A allow-www-traffic-in -m limit --limit 1/second -p tcp --tcp-flags ALL FIN --dport https -j ACCEPT

$IPTABLES -A allow-www-traffic-in -m limit --limit 1/second -p tcp --tcp-flags ALL SYN --dport https -j ACCEPT

$IPTABLES -A allow-www-traffic-in -m state --state NEW,RELATED,ESTABLISHED -p tcp --dport https -j ACCEPT

einfo "Creating outgoing http/https traffic chain"

$IPTABLES -N allow-www-traffic-out

$IPTABLES -F allow-www-traffic-out

$IPTABLES -A allow-www-traffic-out -p tcp --dport www -j ACCEPT

$IPTABLES -A allow-www-traffic-out -p tcp --dport https -j ACCEPT

#Catch portscanners

einfo "Creating portscan detection chain"

$IPTABLES -N check-flags

$IPTABLES -F check-flags

$IPTABLES -A check-flags -p tcp --tcp-flags ALL FIN,URG,PSH -m limit --limit 5/minute -j LOG --log-level alert --log-prefix "NMAP-XMAS:"

$IPTABLES -A check-flags -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP

$IPTABLES -A check-flags -p tcp --tcp-flags ALL ALL -m limit --limit 5/minute -j LOG --log-level 1 --log-prefix "XMAS:"

$IPTABLES -A check-flags -p tcp --tcp-flags ALL ALL -j DROP

$IPTABLES -A check-flags -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -m limit --limit 5/minute -j LOG --log-level 1 --log-prefix "XMAS-PSH:"

$IPTABLES -A check-flags -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP

$IPTABLES -A check-flags -p tcp --tcp-flags ALL NONE -m limit --limit 5/minute -j LOG --log-level 1 --log-prefix "NULL_SCAN:"

$IPTABLES -A check-flags -p tcp --tcp-flags ALL NONE -j DROP

$IPTABLES -A check-flags -p tcp --tcp-flags SYN,RST SYN,RST -m limit --limit 5/minute -j LOG --log-level 5 --log-prefix "SYN/RST:"

$IPTABLES -A check-flags -p tcp --tcp-flags SYN,RST SYN,RST -j DROP

$IPTABLES -A check-flags -p tcp --tcp-flags SYN,FIN SYN,FIN -m limit --limit 5/minute -j LOG --log-level 5 --log-prefix "SYN/FIN:"

$IPTABLES -A check-flags -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP

# Apply and add invalid states to the chains

einfo "Applying chains to INPUT"

$IPTABLES -A INPUT -m state --state INVALID -j DROP

$IPTABLES -A INPUT -j icmp_allowed

$IPTABLES -A INPUT -j check-flags

$IPTABLES -A INPUT -i $LOOPBACK_INTERFACE -j ACCEPT

$IPTABLES -A INPUT -j allow-www-traffic-in

$IPTABLES -A INPUT -j allowed-connection

einfo "Applying chains to OUTPUT"

$IPTABLES -A OUTPUT -m state --state INVALID -j DROP

$IPTABLES -A OUTPUT -j icmp_allowed

$IPTABLES -A OUTPUT -j check-flags

$IPTABLES -A OUTPUT -o $LOOPBACK_INTERFACE -j ACCEPT

$IPTABLES -A OUTPUT -j allow-dns-traffic-out

$IPTABLES -A OUTPUT -j allow-www-traffic-out

$IPTABLES -A OUTPUT -j allowed-connection

eend $?

}

start() {

  ebegin "Starting firewall"

  if [ -e "${FIREWALL}" ]; then

    restore

  else

    einfo "${FIREWALL} does not exists. Using default rules."

    rules

  fi

  eend $?

}

stop() {

  ebegin "Stopping firewall"

  $IPTABLES -F

  $IPTABLES -X

  $IPTABLES -P FORWARD ACCEPT

  $IPTABLES -P INPUT   ACCEPT

  $IPTABLES -P OUTPUT  ACCEPT

  eend $?

}

showstatus() {

  ebegin "Status"

  $IPTABLES -L -n -v --line-numbers

  einfo "NAT status"

  $IPTABLES -L -n -v --line-numbers -t nat

  eend $?

}

panic() {

  ebegin "Setting panic rules"

  $IPTABLES -F

  $IPTABLES -X

  $IPTABLES -P FORWARD DROP

  $IPTABLES -P INPUT   DROP

  $IPTABLES -P OUTPUT  DROP

  $IPTABLES -A INPUT -i lo -j ACCEPT

  $IPTABLES -A OUTPUT -o lo -j ACCEPT

  eend $?

}

save() {

  ebegin "Saving Firewall rules"

  $IPTABLESSAVE > $FIREWALL

  eend $?

}

restore() {

  ebegin "Restoring Firewall rules"

  $IPTABLESRESTORE < $FIREWALL

  eend $?

}

restart() {

  svc_stop; svc_start

}

showoptions() {

  echo "Usage: $0 {start|save|restore|panic|stop|restart|showstatus}"

  echo "start)      will restore setting if exists else force rules"

  echo "stop)       delete all rules and set all to accept"

  echo "rules)      force settings of new rules"

  echo "save)       will store settings in ${FIREWALL}"

  echo "restore)    will restore settings from ${FIREWALL}"

  echo "showstatus) Shows the status"

}Last edited by namron on Thu Sep 23, 2004 2:56 pm; edited 1 time in total

----------

## bakreule

Ahhh...

```
$IPTABLES -P OUTPUT DROP 
```

This is you're problem. The pings aren't getting out of your box at all, I assumed you had a default policy of ACCEPT for your OUTPUT chain.

You should follow the advice of adaptr, and add his line to your script. That will explicity permit icmp ping request packets to leave your system.

You might have a lot of pain with a default OUTPUT policy of DROP. It's much more secure, but you won't be able to get out of the box unless you add a specific rule for what you're trying to do. You did mention it's a server though, so it's probably a good thing....

----------

## namron

Thanks for all your help,  

Will this rule be applied to the OUTPUT chain towards the bottom, or another that I have defined?

Thanks,

Namron

----------

## namron

Ok, my ping requests are getting out, however, now they appear to be getting blocked on the way back.  I'm assuming I need a similar line in my input chain?

Thanks,

Namron

----------

## namron

This worked,  The lines in bold added to my previous icmp section did the trick....  Thanks guys!

#ICMP traffic

  einfo "Creating icmp chain"

  $IPTABLES -N icmp_allowed

  $IPTABLES -F icmp_allowed

#allow pings out from this machine

$IPTABLES -A icmp_allowed -p icmp --icmp-type echo-request -j ACCEPT

$IPTABLES -A icmp_allowed -m state --state ESTABLISHED -p icmp --icmp-type echo-reply -j ACCEPT

  $IPTABLES -A icmp_allowed -m state --state NEW -p icmp --icmp-type time-exceeded -j ACCEPT

  $IPTABLES -A icmp_allowed -m state --state NEW -p icmp --icmp-type destination-unreachable -j ACCEPT

  $IPTABLES -A icmp_allowed -p icmp -j LOG --log-prefix "Bad ICMP traffic:"

  $IPTABLES -A icmp_allowed -p icmp -j DROP

----------

## bakreule

Hmmm... That should be it.... accepting responses is what the following line is for:

```
$IPTABLES -A icmp_allowed -p icmp --icmp-type echo-reply -s $ANYWHERE -i $INTERFACE -j ACCEPT
```

Can you ping localhost? Can you ping some host on your local network? Make sure that whatever host you ping is set up as well to respond to pings.....

If that doesn't work, try adding the line directly on the INPUT chain like this:

```
einfo "Applying chains to INPUT"

$IPTABLES -A INPUT -p icmp --icmp-type echo-reply -s $ANYWHERE -i $INTERFACE -j ACCEPT

$IPTABLES -A INPUT -m state --state INVALID -j DROP

$IPTABLES -A INPUT -j icmp_allowed 

.....
```

----------

