Daniel Ouellet wrote:
Jeff Simmons wrote:
So I just set up a nice spamd for a client, and then watched Google's
Postini try to resend a single email message from just about every IP
they own.
For google, why not get it from the source itself?
Example:
# dig txt _spf.google.com | grep spf
; <<>> DiG 9.3.4 <<>> txt _spf.google.com
;_spf.google.com. IN TXT
_spf.google.com. 187 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 ?all"
Here's a script I use. It handles includes by using recursion, which is
a bit dangerous if there's an endless loop of includes out in the world,
but it's worked for me so far. It will also do DNS lookups for hosts
that are specified by name instead of an IP address and handles sites
that don't put in a FQDN in for the hostname. The output can be fed to
pfctl such as:
pfctl -t local-white -T replace -f /etc/spamd/whitelist.txt
The output from my script for google is: (I actually have a list of
# ./extract_spf spf_hosts.txt
# google.com
# Additional spf: include:_netblocks.google.com
# ==========
# Recursing for additional spf records
# ==========
# _netblocks.google.com
216.239.32.0/19
64.233.160.0/19
66.249.80.0/20
72.14.192.0/18
209.85.128.0/17
66.102.0.0/20
74.125.0.0/16
64.18.0.0/20
207.126.144.0/20
For Hotmail...
# ./extract_spf spf_hosts.txt > /tmp/x
vi # vi /tmp/x
# cat /tmp/x
# microsoft.com
# Additional spf: include:_spf-a.microsoft.com
# Additional spf: include:_spf-b.microsoft.com
# Additional spf: include:_spf-c.microsoft.com
# Additional spf: include:_spf-ssg-a.microsoft.com
# ==========
# Recursing for additional spf records
# ==========
# _spf-a.microsoft.com
216.99.5.67
216.99.5.68
202.177.148.100
203.122.32.250
202.177.148.110
213.199.128.139
213.199.128.145
207.46.50.72
207.46.50.82
# dns lookup delivery.pens.microsoft.com
# dns lookup mh.microsoft.m0.net
# _spf-b.microsoft.com
# dns lookup delivery2.pens.microsoft.com
# dns lookup delivery.smtp.microsoft.com
131.107.65.22
131.107.65.131
131.107.1.101
131.107.1.102
217.77.141.52
217.77.141.59
# _spf-c.microsoft.com
203.32.4.25
213.199.138.181
213.199.138.191
207.46.52.71
207.46.52.79
131.107.1.18
131.107.1.19
131.107.1.20
131.107.70.12
131.107.70.16
86.61.88.25
# _spf-ssg-a.microsoft.com
207.68.169.173/30
207.68.176.1/26
207.46.132.129/27
207.68.176.97/27
65.55.238.129/26
207.46.222.193/26
207.46.116.135/29
65.55.178.129/27
213.199.161.129/27
65.55.33.70/28
# =========
# DNS Lookups
# =========
# delivery.pens.microsoft.com
207.46.248.68
207.46.248.69
207.46.248.64
207.46.248.65
207.46.248.66
207.46.248.67
# mh.microsoft.m0.net
209.11.164.116
# delivery2.pens.microsoft.com
207.46.248.41
207.46.248.42
207.46.248.43
207.46.248.40
# delivery.smtp.microsoft.com
207.46.22.98
207.46.22.101
207.46.248.70
207.46.248.71
#!/bin/sh
if [ $# -ne 1 ]; then
echo "Usage: `basename $0` hostlist_file"
exit 1
fi
if [ ! -f "$1" ]; then
echo "Unable to locate: $1"
exit 1
fi
> /tmp/spf_lookup.$$
> /tmp/more_spf.$$
cat $1 | while read host; do
echo "# $host"
dig $host TXT +short | sed 's/"//g' | \
awk '$1 == "v=spf1" {
num=split($0,stuff," ")
for (i=1;i<=num;i++){
if (substr(stuff[i],1,4)=="ip4:") {
print substr(stuff[i],5)
} else {
if (substr(stuff[i],1,2)=="a:") {
_tmp=substr(stuff[i],3)
_octet=split(_tmp,_tmpsplit,".")
if (_octet==1) {
printf("%s.%s\n", substr(stuff[i],3), host) >> lookup
printf("# dns lookup %s.%s\n", substr(stuff[i],3), host )
} else {
print substr(stuff[i],3) >> lookup
printf("# dns lookup %s\n", substr(stuff[i],3) )
}
} else {
if (substr(stuff[i],1,8)=="include:") {
printf("# Additional spf: %s\n", stuff[i],0)
print substr(stuff[i],9) >> spf
}
}
}
}
}' host=$host lookup="/tmp/spf_lookup.$$" spf="/tmp/more_spf.$$"
done
if [ -s /tmp/spf_lookup.$$ ]; then
echo "# ========="
echo "# DNS Lookups"
echo "# ========="
while read host; do
echo "# $host"
dig $host A +short | grep -v '^;;'
done < /tmp/spf_lookup.$$
fi
if [ -s /tmp/more_spf.$$ ]; then
echo "# =========="
echo "# Recursing for additional spf records"
echo "# =========="
$0 /tmp/more_spf.$$
fi
rm -f /tmp/spf_lookup.$$ /tmp/more_spf.$$
exit 0