Ssh – IPTables: allow outgoing SSH

iptablesssh

I tried to write my rules for securing a web server with just http/https, apt-get updates, sending mails SSH access.
So far I've done that:

IPT=/sbin/iptables
$IPT -F
$IPT -X
$IPT -t nat -F
$IPT -t nat -X
$IPT -t mangle -F
$IPT -t mangle -X
$IPT -P INPUT DROP
$IPT -P FORWARD DROP
$IPT -P OUTPUT DROP
#
$IPT -A INPUT -m state --STATE ESTABLISHED,RELATED -j ACCEPT
$IPT -A OUTPUT -m state --STATE ESTABLISHED,RELATED -j ACCEPT
#
# Allow All for SSH
$IPT -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
$IPT -A OUTPUT -o eth0 -p tcp --sport 22 -j ACCEPT
$IPT -A OUTPUT -o eth0 -p tcp --dport 22 -j ACCEPT
#
# Allow all for HTTP / HTTPS
$IPT -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
$IPT -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
$IPT -A OUTPUT -o eth0 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
$IPT -A INPUT -i eth0 -p tcp --sport 443 -m state --state ESTABLISHED -j ACCEPT
#
# Allow loopback traffic
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT
#    
# Allow to be pinged ( Outside => srv )
$IPT -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
$IPT -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
#
# Allow outgoing DNS connections
$IPT -A OUTPUT -p udp -o eth0 --dport 53 -j ACCEPT
$IPT -A INPUT -p udp -i eth0 --sport 53 -j ACCEPT
#
# Apt-get
$IPT -A OUTPUT -p tcp --dport 80 --sport 32786:61000 -j ACCEPT
$IPT -A INPUT -p tcp --dport 80 --sport 32786:61000 -j ACCEPT
$IPT -A OUTPUT -p tcp --dport 32786:61000 --sport 80 -j ACCEPT
$IPT -A INPUT -p tcp --dport 32786:61000 --sport 80 -j ACCEPT
#
# SMTP Outgoing
$IPT -A OUTPUT -p tcp --sport 1024:65535 -d 0/0 --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT
$IPT -A INPUT -p tcp -s 0/0 --sport 25 --dport 1024:65535 -m state --state ESTABLISHED-j ACCEPT
#
# Prevent DoS
#$IPT -A INPUT -p tcp --dport 80 -m limit --limit 60/minute --limit-burst 150 -j ACCEPT
$IPT -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 100 --connlimit-mask 32     -j REJECT --reject-with tcp-reset
#
# Log dropped packets
$IPT -N LOGGING
$IPT -A INPUT -j LOGGING
$IPT -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables Packet Dropped: "     --log-level 7
$IPT -A LOGGING -j DROP
#
$IPT -L

But it seems I missed something for outgoing SSH to work (from this server to a remote, the other way works), but I can't find what. I also tried to ssh the destination by typing the IP in case some DNS stuff was blocked but that didn't work either.

I am pretty sure that those rules are the reason it doesn't work because it work well if I try to flush and accept all.

Here is the iptables -L -n output:

Chain INPUT (policy DROP)
 target     prot opt source               destination
 ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22
 ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:80 state NEW,ESTABLISHED
 ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp spt:443 state ESTABLISHED
 ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
 ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0           icmp type 8
 ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0           udp spt:53
 ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp spts:32786:61000 dpt:80
 ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp spt:80 dpts:32786:61000
 ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp spt:25 dpts:1024:65535 state ESTABLISHED
 REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:80 #conn/32 > 100 reject-with tcp-reset
 LOGGING    all  --  0.0.0.0/0            0.0.0.0/0

 Chain FORWARD (policy DROP)
 target     prot opt source               destination

 Chain OUTPUT (policy DROP)
 target     prot opt source               destination
 ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp spt:22
 ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22
 ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp spt:80 state ESTABLISHED
 ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:443 state NEW,ESTABLISHED
 ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
 ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0           icmp type 0
 ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0           udp dpt:53
 ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp spts:32786:61000 dpt:80
 ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp spt:80 dpts:32786:61000
 ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp spts:1024:65535 dpt:25 state NEW,ESTABLISHED

 Chain LOGGING (1 references)
 target     prot opt source               destination
 LOG        all  --  0.0.0.0/0            0.0.0.0/0           limit: avg 2/min burst 5 LOG flags 0 level 7 prefix `IPTables Packet Dropped: '
 DROP       all  --  0.0.0.0/0            0.0.0.0/0

Best Answer

When you have an outgoing connection, the destination port will be 22 so this should be the rule:

$IPT -A OUTPUT -o eth0 -p tcp --dport 22 -j ACCEPT

Also, you should have one rule to cover ESTABLISHED and RELATED on top of the INPUT and OUTPUT chains:

$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Hope this helps.