63 lines
1.2 KiB
Ruby
63 lines
1.2 KiB
Ruby
#!/usr/bin/env ruby
|
|
require 'shellwords'
|
|
require 'ipaddress'
|
|
require 'resolv'
|
|
|
|
class R
|
|
def initialize opts=nil
|
|
@resolv = Resolv::DNS.new opts
|
|
end
|
|
IN = Resolv::DNS::Resource::IN
|
|
|
|
def a( q) @resolv.getresources( q, IN::A) end
|
|
def aaaa( q) @resolv.getresources( q, IN::AAAA) end
|
|
def txt( q) @resolv.getresources( q, IN::TXT) end
|
|
def mx( q) @resolv.getresources( q, IN::MX) end
|
|
|
|
def ip q
|
|
a(q) + aaaa(q)
|
|
end
|
|
end
|
|
|
|
$resolv = R.new
|
|
|
|
def bb d
|
|
$resolv.txt( d).map do |l|
|
|
v, *as = l.data.split( ' ')
|
|
if "v=spf1" == v
|
|
as.map do |a|
|
|
case a
|
|
when /\Aa:(.*)\z/
|
|
$resolv.ip( $1).map( &:address)
|
|
when "mx"
|
|
$resolv.mx( d).map do |l|
|
|
$resolv.ip( l.exchange.to_s).map( &:address)
|
|
end
|
|
when /\Aip[46]:(.*)\z/ then $1
|
|
when /\A(?:redirect=|include:)(.*)\z/ then bb $1
|
|
when /\A[-~+]all/ then nil
|
|
else nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
ARGV.
|
|
flat_map do |d|
|
|
bb( d).
|
|
flatten.
|
|
compact.
|
|
uniq.
|
|
map {|x| IPAddress.parse( x).first.to_string rescue ArgumentError }.
|
|
select {|x| String === x }.
|
|
uniq.
|
|
map {|x| [x, d]}
|
|
end.
|
|
group_by {|(x,d)| x }.
|
|
each {|x,xs| xs.map! &:last }.
|
|
sort_by {|x,ds| x = IPAddress.parse x; [x.class.name, x] }.
|
|
each do |(x,ds)|
|
|
puts "#{x} permit # #{ds.uniq.sort.join ' '}"
|
|
end
|