Shorewall – filtering IMAP/SMTP access to gmail.com domain

gmail-firewall-IMAPDo you need to discover what IP netblocks are owned and operated by Google to perhaps add to your firewall ACLs?

With dynamic zones available in Shorewall, you are able to define firewall rules and to filter network traffic based on the domain name. For example, you can permit IMAPS connection only to gmail.com domain. Problem is that Google cluster is very big and you are always connecting to different IP address. So you can’t define static rules for traffic filtering.

Here is little HOWTO do this.

First install the following Debian packages:

# apt-get install dnsutils ipset xtables-addons-dkms

Google provides usefull way how to retrieve Google’s network ranges. You can discover Google’s netblocks by retrieving following DNS records. Use dig tool to do this (retrieve also _netblocks2 and _netblock3 too):

# dig +short TXT _spf.google.com                                                            
"v=spf1 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com ~all"
# dig IN TXT _netblocks.google.com
; <<>> DiG 9.9.5-2-Debian <<>> IN TXT _netblocks.google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<_netblocks.google.com.  2846    IN      TXT     "v=spf1 ip4:216.239.32.0/19 ip4:64.233.160.0/19 ip4:66.249.80.0/20 ip4:72.14.192.0/18 ip4:209.85.128.0/17 ip4:66.102.0.0/20 ip4:74.125.0.0/16 ip4:64.18.0.0/20 ip4:207.126.144.0/20 ip4:173.194.0.0/16 ~all"

;; Query time: 0 msec
;; SERVER: 10.0.0.1#53(10.0.0.1)
;; WHEN: Wed Mar 25 12:05:02 CET 2014
;; MSG SIZE  rcvd: 254

Extracting IP ranges from dig’s output is easy:

dig +short IN TXT _netblocks{,2,3}.google.com | awk -v RS=" " -v FS=":" '/^ip4:/ { print $2; }'

So let’s create script for extraction (we need to extract IPv6 ranges too). Extracted ranges will be added to kernel’s ipset tables and we can use those tables in shorewall configuration.

Checklist

  • create ipset tables on shorewall startup – modify /etc/default/shorewall config
  • create script /etc/shorewall/gmail-ipset-update.sh
  • configure shorewall
  • schedule periodic update of ipsets

Configure shorewall

Add the following lines to /etc/default/shorewall so we can create ipsets before shorewall starts. Because we are not using dig here, no network is requered for successfull DNS record retrieval. On server startup network is not fully configured yet.

IPSET4='gm4il'
IPSET4_NEW='gm4il_new'
IPSET6='gm6il'
IPSET6_NEW='gm6il_new'

# create ipsets if they doesn't exists
ipset -exist create "$IPSET4" hash:net family inet
ipset -exist create "$IPSET6" hash:net family inet6

I’m using SAVE_IPSETS=Yes parameter in /etc/shorewall/shorewall.conf too.

Now configure shorewall’s zones, hosts and rules:

echo "gm4il:net  ipv4    dynamic_shared" >> /etc/shorewall/zones
echo "gm4il      eth0:dynamic" >> /etc/shorewall/hosts
echo "ACCEPT   fw   gm4il   tcp     993" >> /etc/shorewall/rules

Please, restart your shorewall configuration now. I’m using the following shell combo-command:

dmesg -c; /etc/init.d/shorewall restart ; tail -n 20 /var/log/shorewall-init.log;

Hoping everything is OK with your shorewall setup we continue with ipset configuration.

Create script /etc/shorewall/gmail-ipset-update.sh

Create script bellow, and grant execute permission to this script, and schedule an automatic execution using cron:

#!/bin/sh

#
# gmail-ipset-update.sh
#
# Developed by Lubomir Host <lubomir.host@gmail.com>
# Copyright (c) 2014
# Licensed under terms of GNU General Public License.
# All rights reserved.
#
# Changelog: 
# 2014-03-26 - created
#
# Crontab schedule:
# */5 * * * * /etc/shorewall/gmail-ipset-update.sh > /dev/null
#

if [ -f /etc/default/shorewall ]; then
    . /etc/default/shorewall
fi

DEBUG=: # debug off
#DEBUG=echo # debug on

# "v=spf1 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com ~all"
NETBLOCKS="`dig +short TXT _spf.google.com | awk -v RS=' ' -v FS='include:' '/^include:/ { print $2; }'`"

# create ipsets if they doesn't exists
ipset -exist create "$IPSET4" hash:net family inet
ipset -exist create "$IPSET6" hash:net family inet6

ipset -exist create "$IPSET4_NEW" hash:net family inet
ipset -exist create "$IPSET6_NEW" hash:net family inet6

# list IP ranges for gmail.com - IPv4
for net in `dig +short IN TXT $NETBLOCKS \
    | awk -v RS=" " -v FS=":" '/^ip4:/ { print $2; }' `; do
    $DEBUG "Adding network $net"
    ipset add "$IPSET4_NEW" "$net"
done

# list IP ranges for gmail.com - IPv6
for net in `dig +short IN TXT $NETBLOCKS \
    | awk -v RS=" " -v FS="ip6:" '/^ip6:/ { print $2; }' `; do
    $DEBUG "Adding network $net"
    ipset add "$IPSET6_NEW" "$net"
done

ipset swap "$IPSET4_NEW" "$IPSET4"
ipset swap "$IPSET6_NEW" "$IPSET6"

# cleanup
ipset destroy "$IPSET4_NEW"
ipset destroy "$IPSET6_NEW"

If you are reading here, you should have ipset tables successfully configured and shorewall is configured too. So you can try to connect to your gmail account from your favorite e-mail client. In case of some problem, you will see error message in dmesg:

[192097.956779] Shorewall:fw2net:REJECT:IN= OUT=eth0 SRC=10.0.0.2 DST=173.194.65.108 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=19794 DF PROTO=TCP SPT=52537 DPT=993 WINDOW=29200 RES=0x00 SYN URGP=0
[192097.956860] Shorewall:fw2net:REJECT:IN= OUT=eth0 SRC=10.0.0.2 DST=173.194.65.109 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=49917 DF PROTO=TCP SPT=58540 DPT=993 WINDOW=29200 RES=0x00 SYN URGP=0

Resulting IPSETS are as follows:

# ipset list
Name: gm4il
Type: hash:net
Revision: 4
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 17080
References: 8
Members:
66.102.0.0/20
216.239.32.0/19
64.233.160.0/19
173.194.0.0/16
209.85.128.0/17
207.126.144.0/20
74.125.0.0/16
72.14.192.0/18
66.249.80.0/20
64.18.0.0/20

Name: gm6il
Type: hash:net
Revision: 4
Header: family inet6 hashsize 1024 maxelem 65536
Size in memory: 18008
References: 0
Members:
2404:6800:4000::/36
2800:3f0:4000::/36
2a00:1450:4000::/36
2607:f8b0:4000::/36
2c0f:fb50:4000::/36
2001:4860:4000::/36

And here are resulting iptables rules:

# iptables-save| grep -e 'fw2gm[46]il'
:fw2gm4il - [0:0]
-A eth0_out -m set --match-set gm4il dst -j fw2gm4il
-A fw2gm4il -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A fw2gm4il -p tcp -m tcp --dport 993 -j ACCEPT
-A fw2gm4il -j Reject
-A fw2gm4il -j LOG --log-prefix "Shorewall:fw2gm4il:REJECT:" --log-level 6
-A fw2gm4il -g reject

For IPv6 use the command ip6tables-save| grep -e 'fw2gm[46]il' .

Enjoy your complicated firewall setup! 🙂

3 názory na “Shorewall – filtering IMAP/SMTP access to gmail.com domain

  1. oy2knmore

    So good your post!!!
    I have an developing Shorewall & the fact is we planed to replace the current Juniper by Shorewall, ‚couse new laws force the use of free software.
    I tested your conf & unfortunately it not worked, probably by difference between our zone names. My internet zone i named: inet & your’s: net, then my ‚hash‘ in ipset should be as next:
    ...
    # create ipsets if they doesn't exists
    ipset -exist create "$IPSET4" hash:inet family inet
    ipset -exist create "$IPSET6" hash:inet family inet6
    ...

    Besides, you forget the necessary config for gmail outgoing (secure SMTP), so you should add a rule as next:
    ...
    echo "ACCEPT fw gm4il tcp 465" >> /etc/shorewall/rules
    ...

    I think that the best practices indicate don’t use the firewall for daily jobs, such as net surfing or mailing (by example). So this is unnecessary to set rules: fw-2-inet, ‚couse by default Shoreewall Policies let fw gain any access to anywhere (at least that’s in my config). That rules are more comprensive if applied to an trusted zone such as a LAN (wired or not).
    Any way, your post opened a new horizon for me; so thank u very much.

    1. Ľubomír Host Autor

      You are right. Corresponding shorewall rule is missing in my blog post. This is not a bug, it is a feature, my knowhow. 🙂

      Thanks a lot for positive response. Let me know when you need some help.

      Enjoy!

  2. omy

    Thanks again.
    My apologies due my minimal knowhows about ipset.
    The 1st error was in my propossed code line: ipset -exist create "$IPSET4" hash:inet family inet
    Here inet nothin to do with Shorewall name zone. hash:net is a type of ipset & that is its gramatica.
    2nd error was where I’m ran the mail client (Thunderbird). Actually it’s in a trusted zone, aka: tlan (acronym to: „Trusted LAN“), then Sorewall rules will be:
    ...
    ?COMMENT --> tlan-2-gm4il's_IMAPS rules...
    ACCEPT:info tlan gm4il tcp 993
    ?COMMENT --> tlan-2-gm4il's_SMTPS rules...
    ACCEPT:info tlan gm4il tcp 465
    ...

    3d error was in my file: /etc/shorewall/hosts. Your line code is: echo "gm4il eth0:dynamic" >> /etc/shorewall/hosts, but my tlan iface number is eth2. So my code line i must change to:
    echo "gm4il eth2:dynamic" >> /etc/shorewall/hosts.
    After changes, my Thunderbird worked fine!!!
    After this wekend experience, i already have the need tools to develop other usefull Shorewall rules based on ipset.

Nie je možné pridávať komentáre.