On 27/07/2016 3:06 AM, Dr. Rolf Jansen wrote:
Am 26.07.2016 um 13:23 schrieb Julian Elischer <[email protected]>:
On 26/07/2016 1:41 AM, Dr. Rolf Jansen wrote:
Once a week, the IP ranges are compiled from original sources into a binary
sorted table, containing as of today 83162 consolidated range/cc pairs. On
starting-up, the divert daemon reads the binary file in one block and stores
the ranges into a totally balanced binary search tree. Looking-up a country
code for a given IPv4 address in the BST takes on average 20 nanoseconds on an
AWS-EC2 micro instance. I don't know the overhead of diverting, though. I guess
this may be one or two orders of magnitudes higher. Even though, I won't see
any performance issues.
yes the diversion to user space is not a fast operation. When we wrote it, fast
was 10Mbits/sec.
The firewall tables use a radix tree (*) and might be slower than what you
have, but possibly it might be made up for by not having to do the divert
logic. it's not entorely clear from your description why you look up a country
rather than just a pass/block result, but maybe different sources can access
different countries?.
The basic idea was to develop a facility for ipfw for filtering IPv4 packets by
country code - see: https://github.com/cyclaero/ipdb
I simply put into /etc/rc.conf:
geod_enable="YES"
geod_flags="-a DE:BR:US"
The -a flag tells, that source IP addresses only from these countries are
allowed (i.e. passed through the filter). I added also a -d flag, which means
deny (i.e. drop packets) from the given list of countries.
With that in place, I need to add a respective divert rule to the ipfw ruleset
(the divert port of the geod daemon is 8669, remembering that 8668 is the port
of the natd daemon):
ipfw -q add 70 divert 8669 tcp from any to any 80,443 in recv WAN_if setup
I did similar once using ipfw tables but couldn't find a reliable source of
data.
The IP/CC database is compiled from downloads of the daily published delegation
statistics files of the 5 RIR's. I consider the RIR's being the authoritative
source. Anyway, on my systems the IP/CC-database is updated only weekly,
although, daily updating would be possible. I wrote a shell script for this,
that can be executed by a cron job.
https://github.com/cyclaero/ipdb/blob/master/ipdb-update.sh
<https://github.com/cyclaero/ipdb/blob/master/ipdb-update.sh>
There is another tool called geoip , that I uploaded to GitHub, and that I use
for looking up country codes by IP addresses on the command line.
https://github.com/cyclaero/ipdb/blob/master/geoip.c
This one could easily be extended to produce sorted IP ranges per CC that could
be fed into tables of ipfw. I am thinking of adding a command line option for
specifying CC's for which the IP ranges should be exported, something like:
geoip -e DE:BR:US:IT:FR:ES
And this could print sorted IP-Ranges belonging to the listed countries. For
this purpose, what would be the ideal format for directly feeding the produced
output into ipfw tables?
The format for using tables directly is the same as that used for
routing tables.
so imagine that you had to generate a routing table that sent packets
to two different routers depending on their source.
here's a simple rule set that filters web traffic by such a 'routing
table'
except it's routing to two different rules. It also sorts OUTGOING web
traffic to the same rules.
ipfw -q /dev/stdin <<-DONE
# we hate this guy
table 5 add 1.1.1.0/32 1000
# but all ow our people to visit everyone else in that subnet
table 5 add 1.1.0.0/24 2000
# we block 1.1.2.0 through 1.1.3.255
table 5 add 1.1.2.0/23 1000
# but we allow 1.1.4.0 through to 1.1.7.255
table 5 add 1.1.4.0/22 2000
# etc
table 5 add 1.1.8.0/21 1000
table 5 add 1.2.0.0/16 1000
table 5 add 0.0.0.0/0 2000 # default
check-state # If we already decided what to do, do it
# select out only external traffic, into direction specific rules.
add 400 skipto 500 ip from any to any in recv WAN_if
add 410 skipto 700 ip from any to any out xmit WAN_If
add 320 skipto 10000
# Incoming packets
add 500 skipto tablearg tcp from table(5) to any 80,443 setup
keep-state # sort tcp setup packets between rules 1000 and 2000
add 600 skipto 10000
# outgoing packets
add 700 skipto tablearg tcp from any to table(5) 80,443 setup
keep-state # sort tcp setup packets between rules 100 and 2000
add 800 skipto 10000
add 1000 drop ip from any to any
add 2000 allow ip from any to any
# further processing
add 10000 .. # further processing for non tcp
DONE
for full configurability you could have a rule for each country, and a
number for it in the table:
table 5 add 150.101.0.0/16 10610 # Australia
[...]
add 10610 block tcp from any to any 445 # only allow non encrypted
web to those Aussie scum.
add 10611 allow ip from any to any
then by changing the rules at that location you could change the
policy for a country without changing everything else.
(the downside is that dynamic skipto's are not very efficient as they
do a linear search of the rules, where static skiptos cache the
location of the rule to skip to. it's not a terrible cost but it needs
to be kept in mind. (but faster than a divert socket)
your application becomes an application for configuring the firewall.
(which you do by feeding commands down a pipe to ipfw, which is
started as 'ipfw -q /dev/stdin')
Independent from the actual usage case (geo-blocking), let's talk about divert filtering
in general. The original question which is still unanswered can be generalized to,
whether "dropping/denying" a package simply means 'forget about it' or whether
the divert filter is required to do something more involved, e.g. communicate the
situation somehow to ipfw.
there is no residual information about the packet in the kernel once it has
been passed to the user process.
so just "forgetting to hand it back" is sufficient to drop it.
OK, many thanks, that just answers my original doubt. At least technically, my
daemon handles package dropping correctly, although, more elegant ways can be
imagined to do the same thing.
Best regards
Rolf
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-ipfw
To unsubscribe, send any mail to "[email protected]"
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-ipfw
To unsubscribe, send any mail to "[email protected]"