[RFC][patch] Two new actions: state-allow and state-deny

bycn82 bycn82 at gmail.com
Tue Feb 3 06:54:19 UTC 2015


*cool, I like this, it got some points.*
*though the email is too looooong to be read.*

On 3 February 2015 at 14:44, Julian Elischer <julian at freebsd.org> wrote:

> On 2/3/15 3:17 AM, Lev Serebryakov wrote:
>
>>
>>   I propose two new actions: state-allow and state-deny.
>>
>>   They imply "keep-state" and create new dynamic rules, when called
>> directly, but pass packet to NEXT rule after that (don't stop search).
>>
>>   When they are called as dynamic rule, they acts as "allow" and "deny".
>>
>>   So, stateful firewall with NAT could be rewritten like this:
>>
>> add 1000 skipto 2000 all from any to any out xmit outIface
>> add 1010 skipto 3000 all from any to any in  recv outIface
>>
>> add 2000 state-allow from any to any // keep-state is implied
>> add 2010 nat NR from any to any // No "out" here!
>> add 2020 allow all from any to any
>>
>> add 3000 nat NR from any to any
>> add 3010 check-state // Use dynamic rule based on 2000 as "allow" here
>>
>>   What do you think?
>>
>
> I understand what you are trying to do..
> but part of the usefulness of the state runes is that they
> can be any action, not just allow and deny.
> I might try the following action:
>
> record:  (or record-only)
> it allows the rule to be stored, but the action is not performed.
> on check-state, the rule is performed..
>
> so skipto 2000 ip from me to fred 80 record-only out xmit bge0
> would do nothing but record the session
> and on input the session packet would skipto 2000
>
> you could do deny or accept  as well so it's a superset of what you
> suggest.
> I'm not sure where in the rule record-only shoudl be put..
> maybe
>
> ipfw add 1000 log record-only skipto 2000 tcp from me to fred 80,443 out
> xmit bge0
>
> might be more syntactically correct?
>
> What I would find more useful, is separate state rules for each interface.
> so you could not have the danger of a packet on interface A adding a rule
> that eventually does something unexpected on a packet on interface B.
>
>
> looking at my own rules I don't seem to have a problem..
> --------
> Just for kicks,
> here is the base ipfw script.. just sets up the framework
>
> ---
> #!/bin/sh
>
> fwcmd="/sbin/ipfw"
>
> # Suck in the configuration variables.
> if [ -z "${source_rc_confs_defined}" ]; then
>         if [ -r /etc/defaults/rc.conf ]; then
>                 . /etc/defaults/rc.conf
>                 source_rc_confs
>         elif [ -r /etc/rc.conf ]; then
>                 . /etc/rc.conf
>         fi
> fi
>
>
>         # set these to your outside interface network and netmask and ip
>         oif="tun0"
>         onet="192.168.36.0"
>         omask="24"
>         oip="x.x.x.x"
>
>
>         # set these to your inside interface network and netmask and ip
>         iif="vr0"
>         inet="192.168.2.0"
>         imask="255.255.255.0"
>         iip="192.168.2.21"
>
>         # for not the natd target is us but change this if you
>         # change that in natd.conf
>         natd_target=${oip}
>         work_vpnserver=y.y.y.y
>
> INCOMING=4000
> OUTGOING=8000
> LOCAL=1000
> SET=1
>
>         sysctl net.inet.ip.fw.enable=0
>         ${fwcmd} -q flush
>         ${fwcmd} -q table 1 flush
>         ${fwcmd} -q table 2 flush
>         ${fwcmd} -q table 3 flush
>         ${fwcmd} -q table 4 flush
>
>         ${fwcmd} table 1 add 10.0.0.0/8
>         ${fwcmd} table 1 add 172.16.0.0/12
>         #${fwcmd} table 1 add 192.168.0.0/16
>          # Stop draft-manning-dsua-03.txt (1 May 2000) nets (includes
>          # RESERVED-1, DHCP auto-configuration, NET-TEST, MULTICAST (class
> D),
>          # and class E) on the outside interface
>         ${fwcmd} table 1 add 0.0.0.0/8
>         ${fwcmd} table 1 add 169.254.0.0/16
>         ${fwcmd} table 1 add 192.0.2.0/24
>         ${fwcmd} table 1 add 224.0.0.0/4
>         ${fwcmd} table 1 add 240.0.0.0/4
>
>         # add legit sources of ssh.. DNS is not up yet so use IPs
>         # could add to /etc/hosts I guess.
>         #      myotherhouse.org
>         ${fwcmd} table 2 add a.b.c.d
>         #      work
>         ${fwcmd} table 2 add c.d.e.f/24
>         #      my vps
>         ${fwcmd} table 2 add f.g.h.i/24
>
>         # add legit DNS tcp (zone) sources
>         #      my.dns.friends
>         ${fwcmd} table 3 add m.n.o.p
>         #      my.dns.friend
>         ${fwcmd} table 3 add q.r.s.t
>         #      my.vps
>         ${fwcmd} table 3 add f.g.h.i
>
>         # Add our local networks here
>         ${fwcmd} table 4 add 192.168.2.0/24
>         ${fwcmd} table 4 add 172.16.15.0/24
>
> # common spoofing code
> # --------------- ALL PACKETS START HERE. ------------
>
>         ${fwcmd} set disable ${SET}
>
>         # Stop localhost spoofing
>         ${fwcmd} add 100 pass all from any to any via lo0
>         ${fwcmd} add 200 deny log all from any to 127.0.0.0/8
>         ${fwcmd} add 300 deny log ip from 127.0.0.0/8 to any
>
>         # If we've already decided on it. keep our word.
>         ${fwcmd} add check-state
>
> #-------- Interception rules for external interfaces go here -------
>
> #-------- Internal traffic. generally don't care
>         # except to stop spoofing.
>         # make extra sure we don't block DHCP to our server (me)
>         # as initial request will be from 0.0.0.0/0
>
>         ${fwcmd} add ${LOCAL} set ${SET} allow udp from any to any 67 in
> recv ${iif}
>         ${fwcmd} add allow udp from any 67 to any out xmit ${iif}
>
>         # other wise it has to be to and from a net we actually have.
>         ${fwcmd} add deny log all from not "table(4)" to any in recv ${iif}
>         ${fwcmd} add deny log all from any to not "table(4)" out xmit
> ${iif}
>
>         ${fwcmd} add reject log tcp from "table(5)" to any 80,443 in recv
> vr0
>
>         ${fwcmd} add allow ip from any to any
>
>
>
>         sysctl net.inet.ip.fw.enable=1
>
> --------
> and now the rules for my external interface..
> you run this after the other file. note that the rules go into a separate
> set
> and can be disabled at once.
>
> #!/bin/sh
> set -x
> fwcmd="/sbin/ipfw"
>
> # Suck in the configuration variables.
> if [ -z "${source_rc_confs_defined}" ]; then
>         if [ -r /etc/defaults/rc.conf ]; then
>                 . /etc/defaults/rc.conf
>                 source_rc_confs
>         elif [ -r /etc/rc.conf ]; then
>                 . /etc/rc.conf
>         fi
> fi
>
>         # set these to your outside interface network and netmask and ip
>         oif="vr2"
>         oip="$1"
>         onet="$2"
>         omask="$3"
>
>
>         # set these to your inside interface network and netmask and ip
>         iif="vr0"
>         inet="192.168.2.0"
>         imask="255.255.255.0"
>         iip="192.168.2.21"
>
>         # for not the natd target is us but change this if you
>         # change that in natd.conf
>         natd_target=${oip}
>         work_vpnserver=64.244.102.15
>
> INTERCEPT=610
> INCOMING=14000
> OUTGOING=18000
> NATD2=8669
> SET=2
>
>         sysctl net.inet.ip.fw.enable=0
>         ${fwcmd} -q delete ${INTERCEPT}
>         ${fwcmd} set disable ${SET}
>         # effectively clear it
>         ${fwcmd} set move 30 to ${SET}
>
>
> # common spoofing code
> # --------------- ALL PACKETS START HERE. ------------
>
>
>         ${fwcmd} add ${INTERCEPT} set ${SET} skipto ${INCOMING} ip from
> any to any in recv ${oif}
>         ${fwcmd} add ${INTERCEPT} set ${SET} skipto ${OUTGOING} ip from
> any to any out xmit ${oif}
>
> #-------- Internal traffic. generally don't care
> Add in a new incoming and outgoing section for the new interface
>
> #------- INCOMING
>         # don't allow packets from the wrong net!
>         ${fwcmd} add ${INCOMING} set ${SET} deny log all from "table(4)"
> to any
>
>         # in fact don't accept packets that are not for this interface
> exactly
>         ${fwcmd} add set ${SET} deny log ip from any to not ${oip}
>
>         # Allow access to our ssh from trusted places (work, freebsd
> (sometimes))
>         ${fwcmd} add set ${SET} pass tcp from "table(2)" to ${oip} 22
> setup keep-state
>
>         # allow our DNS secondaries to get zone transfers
>         ${fwcmd} add set ${SET} pass tcp from "table(3)" to ${oip} 53
> setup keep-state
>
>         # allow DNS requests, since we are authoratitive
>         ${fwcmd} add set ${SET} pass udp from any to ${oip} 53
>
>         # Allow setup of incoming email # not on this interface
>
>         # me, DNS and root can start outgoing sessions and have
>         # them come in if there is a waiting socket
>         #  !!@#  Don't do this it breaks ntp from inside
> #       ${fwcmd} add set ${SET} allow ip from any to ${oip} uid 0
> #       ${fwcmd} add set ${SET} allow ip from any to ${oip} uid 53
> #       ${fwcmd} add set ${SET} allow ip from any to ${oip} uid 1000
>
>         # ignore any mention of RFC1918 nets on the outside interface
>         ${fwcmd} add set ${SET} deny log all from any to "table(1)"
>         # except the
>         ${fwcmd} add set ${SET} deny log not icmp from "table(1)" to any
>
> #^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v INCOMING NAT POINT
> ^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v
>         # NAT anything that is left and trust NATD
>         ${fwcmd} add set ${SET} divert ${NATD2} all from any to any
>
> #After translation.. trust Nat to filter non matches
>
>         # explicitly allow NAT-T from the vpn server to inside nets
>         ${fwcmd} add set ${SET} allow udp from ${work_vpnserver} to
> "table(4)"
>
>         # Allow TCP through if setup succeeded .
>         # bypass the logging step. too much data
>         ${fwcmd} add set ${SET} allow tcp from any to any established
>
>         # take note of unexpected stuff. then drop it.
>         # hmm, NAtd must have let this through  why?
>         ${fwcmd} add set ${SET} drop log ip from any to ${natd_target}
>
>         # Allow IP fragments to pass through  (NOPE)
>         # ${fwcmd} add set ${SET} pass all from any to any frag
>
>         # XXX remove this if you turn on the target option on
>         # natd to allow a server
>         # Reject & Log all setup of incoming connections from the outside
>         # that have not been explicitly allowed above.
>         ${fwcmd} add set ${SET} deny log tcp from any to ${natd_target}
> setup
>
>         # anything here should be logged. it's intersting.
>         ${fwcmd} add set ${SET} count log ip from any to any
>
>         # after that gauntlet, allow it to proceed.
>         ${fwcmd} add set ${SET} allow ip from any to any
>
>
>
> #----- OUTGOING
>         # Stop RFC1918 nets getting out to the outside interface
>         # except for the wierdness of our next hop being such an address.
>         ${fwcmd} add ${OUTGOING} set ${SET} allow icmp from ${oip} to
> ${onet}:${omask} keep-state
>         ${fwcmd} add set ${SET} deny log all from any to "table(1)"
>
>         # The firewall and inside can talk out if it wants to.
>         # these are local sessions by definition.
>         ${fwcmd} add set ${SET} pass all from ${oip} to any keep-state
>
> #^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v OUTGOING NAT POINT
> ^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v
>         ${fwcmd} add set ${SET} divert ${NATD2} all from any to any out
> recv ${iif}
>
>         # just in case natd goes wierd.
>         ${fwcmd} add set ${SET}  deny log all from "table(1)" to any
>         # in fact don't allow packets out  that are not from this
> interface exactly
>         ${fwcmd} add set ${SET} deny log ip from not ${oip} to any
>         ${fwcmd} add set ${SET} allow all from any to any
>
>         ${fwcmd} set enable ${SET}
>         sysctl net.inet.ip.fw.enable=1
>
> and here's rules for un untrusted tunnel
> this file can also be run after the main one when hte tunnel is in use.
> I'm not using this one at the moment, so I'm not sure it works but you can
> get the idea..
> I add a separate script file for each interface.. and they slot in
> separate rules as needed.
>
> #!/bin/sh
> fwcmd="/sbin/ipfw"
>
> # Suck in the configuration variables.
> if [ -z "${source_rc_confs_defined}" ]; then
>         if [ -r /etc/defaults/rc.conf ]; then
>                 . /etc/defaults/rc.conf
>                 source_rc_confs
>         elif [ -r /etc/rc.conf ]; then
>                 . /etc/rc.conf
>         fi
> fi
>
>
>
>         # set these to your inside interface network and netmask and ip
>         iif="vr0"
>         inet="192.168.2.0"
>         imask="255.255.255.0"
>         iip="192.168.2.21"
>
>         # set these to your outside interface network and netmask and ip
>         oif="tun0"
>         onet="192.168.36.0"
>         omask="24"
>         oip="l.m.n.o"
> INTERCEPT=500
> INCOMING=4000
> OUTGOING=8000
> SET=1
>
>         # for now the natd target is us but change this if you
>         # change that in natd.conf
>         natd_target=${oip}
>         work_vpnserver=t.u.v.w
>
>         sysctl net.inet.ip.fw.enable=0
>
> #-------- Select direction and interface class
>         ${fwcmd} add ${INTERCEPT} set ${SET} skipto ${INCOMING} ip from
> any to any in recv ${oif}
>         ${fwcmd} add ${INTERCEPT} set ${SET} skipto ${OUTGOING} ip from
> any to any out xmit ${oif}
>
>
> #------- INCOMING
>         # don't allow packets from the wrong net!
>         ${fwcmd} add ${INCOMING} set ${SET} deny log all from "table(4)"
> to any
>
>         # in fact don't accept packets that are not for this interface
> exactly
>         ${fwcmd} add set ${SET} deny log ip from any to not ${oip}
>
>         # Allow access to our ssh from trusted places (work, freebsd,
> (sometimes))
>         ${fwcmd} add set ${SET} pass tcp from "table(2)" to ${oip} 22
> setup keep-state
>
>         # allow our DNS secondaries to get zone transfers
>         ${fwcmd} add set ${SET} pass tcp from "table(3)" to ${oip} 53
> setup keep-state
>
>         # allow DNS requests, since we are authoratitive
>         ${fwcmd} add set ${SET} pass udp from any to ${oip} 53
>
>         # Allow setup of incoming email
>
>         # julian and root can start outgoing sessions and have them come
> in if there is a waiting socket :-)
>         ${fwcmd} add set ${SET} allow ip from any to ${oip} uid 0
>         ${fwcmd} add set ${SET} allow ip from any to ${oip} uid 53
>         ${fwcmd} add set ${SET} allow ip from any to ${oip} uid 1000
>
>         # ignore any mention of RFC1918 nets on the outside interface
>         ${fwcmd} add set ${SET} deny log all from any to "table(1)"
>         ${fwcmd} add set ${SET} deny log not icmp from "table(1)" to any
>
> #^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v INCOMING NAT POINT
> ^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v
>         # NAT anything that is left and trust NATD
>         ${fwcmd} add set ${SET} divert natd all from any to any
>
> #After translation
>
>         # explicitly allow NAT-T from the vpn server to inside nets
>         ${fwcmd} add set ${SET} allow udp from ${work_vpnserver} to
> "table(4)"
>
>         # Allow TCP through if setup succeeded .
>         # bypass the logging step. too much data
>         ${fwcmd} add set ${SET} allow tcp from any to any established
>
>         # take note of unexpected stuff. then drop it.
>         ${fwcmd} add set ${SET} drop log ip from any to ${natd_target}
>
>         # Allow IP fragments to pass through  (NOPE)
>         # ${fwcmd} add set ${SET} pass all from any to any frag
>
>         # XXX remove this if you turn on the target option on
>         # natd to allow a server
>         # Reject & Log all setup of incoming connections from the outside
>         # that have not been explicitly allowed above.
>         ${fwcmd} add set ${SET} deny log tcp from any to ${natd_target}
> setup
>
>         # anything here should be logged. it's interesting.
>         ${fwcmd} add set ${SET} count log ip from any to any
>
>         #currently slam that door .. this rule comes and goes depending on
> if I need it.
>         ${fwcmd} add set ${SET} deny log ip from any to any
>
>         # after that gauntlet, allow it to proceed.
>         ${fwcmd} add set ${SET} allow ip from any to any
>
>
>
> #----- OUTGOING
>         # Stop RFC1918 nets getting out to the outside interface
>         # except for the wierdness of our next hop being such an address.
>         ${fwcmd} add ${OUTGOING} set ${SET} allow icmp from ${oip} to
> ${onet}/${omask} keep-state
>         ${fwcmd} add set ${SET} deny log all from any to "table(1)"
>
>         # The firewall (and my laptop) can talk out if it wants to.
>         # these are local sessions by definition.
>         ${fwcmd} add set ${SET} pass all from ${oip} to any keep-state
> #       ${fwcmd} add set ${SET} pass udp from ${oip} to any keep-state
> #       ${fwcmd} add set ${SET} pass icmp from ${oip} to any keep-state
>
>         # Allow NTP queries out in the world from the firewall.
> #       ${fwcmd} add set ${SET} pass udp from ${oip} to any 123 keep-state
>
>         # Allow DNS queries out in the world from the firewall.
> #       ${fwcmd} add set ${SET} pass udp from ${oip} to any 53 keep-state
>
> #^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v OUTGOING NAT POINT
> ^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v
>         ${fwcmd} add set ${SET} divert natd all from any to any out recv
> ${iif}
>
>         # just in case natd goes wierd.
>         ${fwcmd} add set ${SET}  deny log all from "table(1)" to any
>         # in fact don't allow packets out  that are not from this
> interface exactly
>         ${fwcmd} add set ${SET} deny log ip from not ${oip} to any
>         ${fwcmd} add set ${SET} allow all from any to any
>
>         ${fwcmd} set enable ${SET}
>
>         sysctl net.inet.ip.fw.enable=1
>
>
>
>
> _______________________________________________
> freebsd-ipfw at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-ipfw
> To unsubscribe, send any mail to "freebsd-ipfw-unsubscribe at freebsd.org"
>


More information about the freebsd-net mailing list