Security Consulting
  Unix Administration     Firewall     Intrusion Detection     Network Security     Hacking     MORE     HOME    

OpenBSD as a Firewall

When I set up my OpenBSD firewall, I started to compile a script where I recorded all the changes on the system. It includes commands which delete files on the system which are not needed.
Be warned, there is no prompt on what it deltes. For a secure Firewall just all right!

DOWNLOAD Script
Last changed: March 2001

Resource

  • A nice resource for the 3.3 packetfilter is on oreilly.
  • The developer of OpenBSD is Daniel Hartmeier, a Swiss guy, how else could it be? His page is great and contains all the information you need to have about PF.

    ftp-proxy

    Use the ftp-proxy to let ftp connections through your firewall in a more controlled manner. The setup is as follows:
    pf.conf
      pass in log quick on $int proto tcp from $internalnet to 127.0.0.1 port 8081 flags S/SAFR keep state
      pass out log quick on $ext proto tcp from $ext port 49200 >< 49300 to any flags S/SAFR keep state
      pass in log quick on $ext proto tcp from any port 20 to $ext port 49200 >< 49300 flags S/SAFR keep state
    nat.conf
      rdr on de1 from any to any port 21 -> 127.0.0.1 port 8081
    inetd.conf
      127.0.0.1:8081 stream tcp nowait root /usr/libexec/ftp-proxy ftp-proxy -m 49200 -M 49300
    Don't forget to:
      pfctl -N /etc/nat.conf -R /etc/pf.conf -e
      inetd
    If you want to use tcp wrapper, use the following:
      127.0.0.1:8081 stream tcp nowait root /usr/libexec/tcpd ftp-proxy -m 49200 -M 49300
    Adopt the hosts.deny and hosts.allow files:
      hosts.deny: ALL: ALL
      hosts.allow: ftp-proxy: x.y.z.a

    PF

    From version 3.0 of OpenBSD on, ipf is not used any more, but pf is its substitute. The rules are pretty much compatible, but there are some things to take care of:
  • "log first" is not supported any more.
  • "with opt xxx" can not be defined any more. Per default all the packets with strange options are droped.
  • "with xxx" same is true here. I don't really know if I like that!!! I DON'T!!!
  • When you have ICMP things, you NEED to define the protocol family:
      pass in log on de0 proto icmp from any to any icmp-type unreach code 1 # host-unr
    has to become:
      pass in log on de0 inet proto icmp from any to any icmp-type unreach code 1 # host-unr
  • Rules which do not define the protocol and use the port directive are not working any more:
      pass in quick on ne3 from 212.71.102.162 to 212.71.102.170 port = 53
    needs to be:
      pass in quick on ne3 proto { tcp, udp } from 212.71.102.162 to 212.71.102.170 port = 53
  • pf is really picky:
      pass in quick on ne3 proto { tcp, udp} from 212.71.102.162 to 212.71.102.170 port = 53
    (having the curly breacket right after the udp, does not work!
  • To log the packets, you have to enable the pseudodevice pflog0:
      ifconfig pflog0 up
    and start pflogd. (The two things are done if in rc.conf the PF=YES line is enabled.
  • To read the logs, use:
      tcpdump -n -e -ttt -r /var/log/pflog

    A nice reference to IPF which also applies to PF in some cases is IPF HowTO.

    PF Data Analysis

    There is a nice package, called aguri to graphically analyze pf-data!

    Fighting SPAM with PF

    Under my SPAM pages I describe a little Tarpit setup and also link to Bezendrine's page that ellaborates a bit more how it works. Fighting SPAM? This is the way to do it!

    PF Rev. 1.102 (OpenBSD 3.2) Value Reference

    Have you ever wondered what icmp-types there are in pf? Check the source and it shows the following:
    static const struct icmptypeent icmp_type[] = {
            { "echoreq",        ICMP_ECHO },
            { "echorep",        ICMP_ECHOREPLY },
            { "unreach",        ICMP_UNREACH },
            { "squench",        ICMP_SOURCEQUENCH },
            { "redir",        ICMP_REDIRECT },
            { "althost",        ICMP_ALTHOSTADDR },
            { "routeradv",        ICMP_ROUTERADVERT },
            { "routersol",        ICMP_ROUTERSOLICIT },
            { "timex",        ICMP_TIMXCEED },
            { "paramprob",        ICMP_PARAMPROB },
            { "timereq",        ICMP_TSTAMP },
            { "timerep",        ICMP_TSTAMPREPLY },
            { "inforeq",        ICMP_IREQ },
            { "inforep",        ICMP_IREQREPLY },
            { "maskreq",        ICMP_MASKREQ },
            { "maskrep",        ICMP_MASKREPLY },
            { "trace",        ICMP_TRACEROUTE },
            { "dataconv",        ICMP_DATACONVERR },
            { "mobredir",        ICMP_MOBILE_REDIRECT },
            { "ipv6-where",        ICMP_IPV6_WHEREAREYOU },
            { "ipv6-here",        ICMP_IPV6_IAMHERE },
            { "mobregreq",        ICMP_MOBILE_REGREQUEST },
            { "mobregrep",        ICMP_MOBILE_REGREPLY },
            { "skip",        ICMP_SKIP },
            { "photuris",        ICMP_PHOTURIS }
    };
    The following are the ICMP Codes:
    static const struct icmpcodeent icmp_code[] = {
            { "net-unr",                ICMP_UNREACH,        ICMP_UNREACH_NET },
            { "host-unr",                ICMP_UNREACH,        ICMP_UNREACH_HOST },
            { "proto-unr",                ICMP_UNREACH,        ICMP_UNREACH_PROTOCOL },
            { "port-unr",                ICMP_UNREACH,        ICMP_UNREACH_PORT },
            { "needfrag",                ICMP_UNREACH,        ICMP_UNREACH_NEEDFRAG },
            { "srcfail",                ICMP_UNREACH,        ICMP_UNREACH_SRCFAIL },
            { "net-unk",                ICMP_UNREACH,        ICMP_UNREACH_NET_UNKNOWN },
            { "host-unk",                ICMP_UNREACH,        ICMP_UNREACH_HOST_UNKNOWN },
            { "isolate",                ICMP_UNREACH,        ICMP_UNREACH_ISOLATED },
            { "net-prohib",                ICMP_UNREACH,        ICMP_UNREACH_NET_PROHIB },
            { "host-prohib",        ICMP_UNREACH,        ICMP_UNREACH_HOST_PROHIB },
            { "net-tos",                ICMP_UNREACH,        ICMP_UNREACH_TOSNET },
            { "host-tos",                ICMP_UNREACH,        ICMP_UNREACH_TOSHOST },
            { "filter-prohib",        ICMP_UNREACH,        ICMP_UNREACH_FILTER_PROHIB },
            { "host-preced",        ICMP_UNREACH,        ICMP_UNREACH_HOST_PRECEDENCE },
            { "cutoff-preced",        ICMP_UNREACH,        ICMP_UNREACH_PRECEDENCE_CUTOFF },
            { "redir-net",                ICMP_REDIRECT,        ICMP_REDIRECT_NET },
            { "redir-host",                ICMP_REDIRECT,        ICMP_REDIRECT_HOST },
            { "redir-tos-net",        ICMP_REDIRECT,        ICMP_REDIRECT_TOSNET },
            { "redir-tos-host",        ICMP_REDIRECT,        ICMP_REDIRECT_TOSHOST },
            { "normal-adv",                ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NORMAL },
            { "common-adv",                ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NOROUTE_COMMON },
            { "transit",                ICMP_TIMXCEED,        ICMP_TIMXCEED_INTRANS },
            { "reassemb",                ICMP_TIMXCEED,        ICMP_TIMXCEED_REASS },
            { "badhead",                ICMP_PARAMPROB,        ICMP_PARAMPROB_ERRATPTR },
            { "optmiss",                ICMP_PARAMPROB,        ICMP_PARAMPROB_OPTABSENT },
            { "badlen",                ICMP_PARAMPROB,        ICMP_PARAMPROB_LENGTH },
            { "unknown-ind",        ICMP_PHOTURIS,        ICMP_PHOTURIS_UNKNOWN_INDEX },
            { "auth-fail",                ICMP_PHOTURIS,        ICMP_PHOTURIS_AUTH_FAILED },
            { "decrypt-fail",        ICMP_PHOTURIS,        ICMP_PHOTURIS_DECRYPT_FAILED }
    };
    
    Here are the PF-Timeouts:
    const struct pf_timeout pf_timeouts[] = {
            { "tcp.first",                PFTM_TCP_FIRST_PACKET },
            { "tcp.opening",        PFTM_TCP_OPENING },
            { "tcp.established",        PFTM_TCP_ESTABLISHED },
            { "tcp.closing",        PFTM_TCP_CLOSING },
            { "tcp.finwait",        PFTM_TCP_FIN_WAIT },
            { "tcp.closed",                PFTM_TCP_CLOSED },
            { "udp.first",                PFTM_UDP_FIRST_PACKET },
            { "udp.single",                PFTM_UDP_SINGLE },
            { "udp.multiple",        PFTM_UDP_MULTIPLE },
            { "icmp.first",                PFTM_ICMP_FIRST_PACKET },
            { "icmp.error",                PFTM_ICMP_ERROR_REPLY },
            { "other.first",        PFTM_OTHER_FIRST_PACKET },
            { "other.single",        PFTM_OTHER_SINGLE },
            { "other.multiple",        PFTM_OTHER_MULTIPLE },
            { "frag",                PFTM_FRAG },
            { "interval",                PFTM_INTERVAL },
            { NULL,                        0 }
    };
    
    All the values for IPv6 you have to check in the source.

    IPF

    When using ipfilter, use the following commands:
      ipf -D Disables the active rules
      ipf -Fa -f /etc/ipf.rules -E Enables the /etc/ipf.rules



    CopyLeft (l) 2003 by Raffael Marty