1st January 2009

Windows Firewall

At work, I am stuck with Windows for the time being. Windows sucks, especially with regard to networking. I want a decent packet filtering and network address translation engine. Something resembling OpenBSD Packet Filter (PF) or Netfilter (iptables) will do. I absolutely require flexible NAT functionality. I do not care about userland processes (personal firewall would be a separate project). The solution must be open source under an OSS approved license. Performance is not an issue I care about too much. Security on the other hand clearly is very important. Minimizing source changes on ported source code is a must.

Plan B

The current plan B is to implement a custom packet filter and NAT engine. The current implementation does static packet filtering based on an internal bytecode interpreter. It works but the rules currently have to be hardcoded into the driver in form of bytecode and there is no connection tracking or network address translation.

Original Plan

This is a thoroughly evil effort to port PF to Windows. This project is in the design and early implementation phase. A working and installable NDIS IM filter driver exists, and work is on its way to port the pf bits and write glue code to allow the core PF code to build with minimal source changes.

To Do

  1. Analyze how PF handles packet modifications and other mbuf related issues like storing information in the mbuf, and design how to support this in a NDIS IM driver.
  2. Analyze how PF handles network interfaces and design how to support this in a NDIS IM driver. [what is the impact on pf_if]
  3. Analyze what parts of the config file format and userland utilities need Windows specific changes and design these changes. Especially design a unobtrusive and stable way to handle network interface names including things like wildcard and network address range syntax support. Can we use the NDIS names? How to access NDIS names from userspace? What to use as internal handle on NIC? Where to translate from symbolic names to internal handle, and using which API?
  4. Analyze the PF userland/kernel interface and design that interface on Windows. [compare ioctl mechanism differences and impact on pf_ioctl code; how to enforce admin rights]
  5. Port the PF kernel bits.
  6. Port the PF userland bits.
  7. Test, test, test.
  8. Enjoy…
  9. Come back and port additional features like pflog, pfsync, authpf, ftp-proxy.

Current Design

  • NDIS 4.0/5.1 IM filter driver (2k and XP, not NT/9X/ME)
  • OpenBSD PF port with minimal source changes guarded by ifdef’s
    • Required: stateful packet filtering, NAT, tables, pfctl
    • Nice to have: passive OS detection
    • Maybe later: pflog, pfsync, authpf, ftp-proxy
    • Probably very hard: ALTQ, bridging, IPsec
  • rewrite ioctl interfaces to expose functionality to userland
  • translate NDIS_PACKET somehow into a mbuf for pf processing
    • interface handling?
    • mbuf tags?

PF Entry Points

**pf.c** pf_find_mtag() pf_get_mtag() pf_tag_packet() pf_test() pf_test6()
net/if_bridge.c - - yes yes yes
net/if_ethersubr.c get routed - - - -
net/if_fddisubr.c get routed - - - -
net/if_tokensubr.c get routed - - - -
netinet/ip_icmp.c copy tag gen'd copy tag gen'd - - -
netinet/ip_input.c get rtableid - - yes -
netinet/ip_output.c - - - yes -
netinet/ipsec_input.c - - yes - -
netinet/ipsec_output.c - - yes - -
netinet/tcp_input.c get xlate localhost - - - -
netinet/udp_usrreq.c get xlate localhost - - - -
netinet6/ip6_forward.c yes - - - yes
netinet6/ip6_input.c yes - - - yes
netinet6/ip6_output.c - - - - yes
**pf_ioctl.c** pf_tag_unref() pf_tagname2tag() pf_tag2tagname()
net/if_bridge.c yes yes yes
net/pfkeyv2_convert.c - yes yes
netinet/ip_ipsp.c yes - -
**pf_if.c** pfi_attach_ifnet() pfi_detach_ifnet() pfi_attach_ifgroup() pfi_detach_ifgroup() pfi_group_change()
net/if.c yes yes yes yes yes

PF mbuf Handling

TBD

PF Interface Handling

TBD

PF ioctl Interface

TBD

Windows Packet Filtering Method Comparison

General packet filtering:

  • NDIS IM Filter
    • PRO: ideal place in stack, official, portable
    • CON: difficult to install, problems with RAS/WAN (especially with 9x/ME/NT)
  • NDIS Hook
    • PRO: ideal place in stack, more-or-less-portable
    • CON: inofficial, hackish, fragile, needs VxD hacks on 9x/ME
  • IP Filter Hook
    • PRO: easy to use, semi-official
    • CON: first come first serve (only first driver will work), limitations with sent packets, not portable
  • Firewall Hook
    • PRO: easy to use, semi-official
    • CON: limited to basic header information, not portable

Personal firewall style application sandboxing:

  • TDI Hook
    • PRO: control applications, users
    • CON: too high up the protocol stack (above routing), does not protect OS very well
  • Winsock 2 Hook
    • PRO: control applications, users, portable
    • CON: easy to bypass for applications

Concepts

Implementations

Open Source

Closed Source

  • Winpk Filter Tech Notes
  • CORE FORCE The firewall component of CORE FORCE is a Windows port of OpenBSD’s PF, the open source, mature, server-level firewall (PF: The OpenBSD Packet Filter). PF’s functionality has been trimmed and tailored to make it suitable for desktop systems and to minimize code complexity. CORE FORCE support inbound and outbound stateful filtering with advanced settings such as TCP flags and ICMP type/code flags. It works on a per application basis, loading and unloading rules dynamically at application runtime and it can be configured to require runtime user confirmation on certain connections. It is implemented at kernel level as an intermediate driver that mediates communications between the network card drivers and the operating system’s TCP/IP protocol stack, making it difficult to bypass.