.-----------------------------------------------------------------------------. | | |---/ IPSEC Bridging Under OpenBSD (or: Plugging Holes With Your Fingers) /---| | | `-----------------------------------------------------------------------------' azure@osuny.co.uk ================================== http://azure.osuny.co.uk /Intro In a previous article I outlined one method for integrating Windows networks into a secure VPN with IPSEC and Samba. This time around I'm going to demonstrate an alternative method of achieving what is essentially the same functionality in a completely different way. Your mileage may have varied in trying to juggle separate subnets, identical/different Domains, and NetBIOS integrity across your VPN. In this instance the connection we'll create is not tied to any particular proprietary protocols or services; yet may actually end up serving your purposes in a more ideal fashion. It is also a much simpler method of joining remote Local Area Networks that may not need to be functionally separated at all. Cutting directly to the chase: IPSEC bridging is essentially the same as the traditional interface bridging you are already familiar with. One minor exception is that the OSI layer-2 information is propagated across the VPN instead of merely across your physical hardware. Generally however: As above, so below. For our purposes in this example we will bridge two remote LANs; each with physically separate internal and external interfaces. [Net-1]----> [bridge1/IPF] <--------> [bridge2/IPF] <----[Net-2] An interface on Net-1 is bridged to an interface on Net-2. Ethernet frames are encapsulated and sent across the VPN where they are stripped out and placed back on the wire by the bridging code itself. The OpenBSD boxes will be serving only as hardware bridging devices - we will not concern ourselves with how users gain access to the Internet in general. It is not even necessary for the client machines to know the bridges exist (or to have normal Internet connectivity at all, for that matter). Unlike in the previous article, this time OpenBSD is *completely* transparent to endusers. /Configuring OpenBSD's Implementation This will differ depending on your particular installation of OpenBSD. The syntax for ipsecadm(8) has changed with every release since its integration into the base operating system. The examples included in this document will assume OpenBSD 2.8-RELEASE. Leaving aside the politics of our multi-party system (*BSD, Linux, etc.), OpenBSD is a robust player in the UNIX game; and also includes all the tools we need in its default install. --/Customizing and Patching the Kernel for Load However, customizing the kernel to fit specific hardware is always a good idea. It cuts down the size of the file that is loaded into memory; thus increasing system performance. There are also changes you can make to maximize networking performance. Some additional options you'll want to include in your config before recompiling are: option IPFORWARDING option IPFILTER option IPFILTER_LOG option NMBCLUSTERS = 8192 For additional information on tuning, see the OpenBSD performance tuning faq: [ http://www.openbsd.org/faq/faq11.html#11.1 ] Patches should also be applied accordingly. At the time of this writing, no patches have been issued for OpenBSD 2.8. Information on versions prior to 2.8 is available at: [ http://www.openbsd.org/errata.html ] You will need to edit /etc/rc.conf to activate IPFILTER and IPNAT at boot time. You will also need to have net.inet.ip.forwarding=1 net.inet.esp.enable=1 in your /etc/sysctl.conf file. Reboot and rinse. --/IFCONFIG, BRCONFIG and IPSECADM An IPSEC bridge is configured using standard command line tools. An ENC interface is added to the bridge with brconfig(8), and associated with existing SAs using ifconfig(8). ipsecadm is used to create the relevant IPSEC flows. Finally, all interfaces are brought up and layer-2 information begins to travel across the VPN. An example configuration is provided below. First of all we'll need to generate keys for the IPSEC transactions: # openssl rand 20 | hexdump -e '20/1 "%02x"' > KEYFILE_LOCATION # openssl rand 20 | hexdump -e '20/1 "%02x"' > AUTHKEYFILE_LOCATION Then we construct a two-node IPSEC bridge as follows: On both OpenBSD boxes: # brconfig bridge0 add ENC_INTERFACE PRIVATE_INTERFACE # brconfig bridge0 blocknonip (to block non-ip traffic) # brconfig bridge0 link1 (to block ip multicasts) # ipsecadm new esp -spi SPI1 -dst BRIDGE2_PUBLIC_IP -src \ BRIDGE1_PUBLIC_IP -enc blf -auth sha1 -keyfile \ KEYFILE_LOCATION -authkeyfile AUTHKEYFILE_LOCATION # ipsecadm new esp -spi SPI2 -dst BRIDGE1_PUBLIC_IP -src \ BRIDGE2_PUBLIC_IP -enc blf -auth sha1 -keyfile \ KEYFILE_LOCATION -authkeyfile AUTHKEYFILE_LOCATION On BRIDGE1: # ipsecadm flow -dst BRIDGE2_PUBLIC_IP -in -transport etherip \ -require -addr BRIDGE1_PUBLIC_IP 255.255.255.255 \ BRIDGE2_PUBLIC_IP 255.255.255.255 # ifconfig ENC_INTERFACE dstsa BRIDGE2_PUBLIC_IP/SPI1/esp # ifconfig ENC_INTERFACE srcsa BRIDGE1_PUBLIC_IP/SPI2/esp # ifconfig PRIVATE_INTERFACE up (if not already up) # ifconfig ENC_INTERFACE up # brconfig bridge0 up On BRIDGE2: # ipsecadm flow -dst BRIDGE1_PUBLIC_IP -in -transport etherip \ -require -addr BRIDGE2_PUBLIC_IP 255.255.255.255 \ BRIDGE1_PUBLIC_IP 255.255.255.255 # ifconfig ENC_INTERFACE dstsa BRIDGE1_PUBLIC_IP/SPI2/esp # ifconfig ENC_INTERFACE srcsa BRIDGE2_PUBLIC_IP/SPI1/esp # ifconfig PRIVATE_INTERFACE up (if not already up) # ifconfig ENC_INTERFACE up # brconfig bridge0 up It is not strictly necessary for INTERNAL_INTERFACE to have an IP address on either side of the VPN. --/Viewing Stats and Turning the Bridge Off To view a table of MAC addresses functioning on your bridge at any time, use: # brconfig -a Which produces results similar to: bridge0: flags=0<> Interfaces: Addresses (max cache: 100, timeout: 240): bridge1: flags=0<> Interfaces: Addresses (max cache: 100, timeout: 240): To disable the bridge and remove the IPSEC SAs, use: # brconfig bridge0 delete ENC_INTERFACE # brconfig bridge0 delete INTERNAL_INTERFACE # brconfig bridge0 down # ifconfig ENC_INTERFACE down # ifconfig ENC_INTERFACE clearsa 0.0.0.0/0/0 This will return your system to normal (pre-bridge) status. --//Too Lazy To Type I have again written a short perl utility to construct ifconfig(8), brconfig(8) and ipsecadm(8) rules against user-supplied network information. ipsec_bridge_2.8.pl can be retrieved from: [ http://azure.osuny.co.uk/perl/ipsec_bridge_2.8.pl ] You can run the output of this utility on both ends of your would-be VPN to initialize an IPSEC bridge between private interfaces (as is described in detail above). Specific information on the mechanics of IPSEC and bridging themselves are beyond the scope of this article, but can be gleaned from relevant man pages and freely available reference elsewhere on the Internet. --/Filtering For Bandwidth's Sake It all sounds great until you realize that broadcast information on your LAN is also going to be transmitted across your limited bandwidth VPN connection. With Windows-based machines on your network this can quickly spell disaster. Fortunately, the ancient ones have sprinkled the golden dust of their approval upon our efforts: IPF. --//IPF Stateful packet filtering with IPF can protect the bridge from external 'influence' while keeping the frames passing across the VPN from overwhelming both upstream connections. In this example we will filter broadcasts as they come in on the INTERNAL_INTERFACE before they are handed off to the bridge. Keep in mind that a separate filtering rule will have to be added for each network that touches the bridging interface. Other possibilities include filtering on the bridge interface itself. (See bridge(8) for details on filtering at the bridge level.) Included below is a sample template for configuring IPF: xxx.xxx.xxx = relevant portion of the external IP on BRIDGE1 yyy.yyy.yyy = relevant portion of the internal IP on BRIDGE1 aaa.aaa.aaa = relevant portion of the external IP on BRIDGE2 bbb.bbb.bbb = relevant portion of the internal IP on BRIDGE2 on BRIDGE1: # /etc/ipf.rules # # block everything by default unless another rule says otherwise block in log level local0.info on EXTERNAL_INTERFACE # block spoofed traffic on external interfaces block in quick on EXTERNAL_INTERFACE from 127.0.0.0/8 to any block in quick on EXTERNAL_INTERFACE from 10.0.0.0/8 to any block in quick on EXTERNAL_INTERFACE from 172.16.0.0/12 to any block in quick on EXTERNAL_INTERFACE from 192.168.0.0/24 to any block in quick on EXTERNAL_INTERFACE from any to xxx.xxx.xxx.0/32 block in quick on EXTERNAL_INTERFACE from any to xxx.xxx.xxx.255/32 # block broadcast traffic from the internal network block in quick on INTERNAL_INTERFACE from any to yyy.yyy.yyy.0/32 block in quick on INTERNAL_INTERFACE from any to yyy.yyy.yyy.255/32 # pass traffic out from EXTERNAL_INTERFACE and from INTERNAL_NETWORK pass out quick on EXTERNAL_INTERFACE proto tcp/udp from \ BRIDGE1_EXTERNAL_IP/32 to any keep state pass out quick on EXTERNAL_INTERFACE proto icmp from \ BRIDGE1_EXTERNAL_IP/32 to any keep state pass out quick on EXTERNAL_INTERFACE proto tcp/udp from \ BRIDGE1_INTERNAL_NETWORK/24 to any keep state # pass IPSEC traffic for bridge0 and enc1 pass in quick proto esp from BRIDGE2_EXTERNAL_IP/32 to \ BRIDGE1_EXTERNAL_IP/32 pass out quick proto esp from BRIDGE1_EXTERNAL_IP/32 to \ BRIDGE2_EXTERNAL_IP/32 pass in quick on enc1 from BRIDGE2_INTERNAL_NETWORK/24 to \ BRIDGE1_INTERNAL_NETWORK/24 on BRIDGE2: # /etc/ipf.rules # # block everything by default unless another rule says otherwise block in log level local0.info on EXTERNAL_INTERFACE # block spoofed traffic on external interfaces block in quick on EXTERNAL_INTERFACE from 127.0.0.0/8 to any block in quick on EXTERNAL_INTERFACE from 10.0.0.0/8 to any block in quick on EXTERNAL_INTERFACE from 172.16.0.0/12 to any block in quick on EXTERNAL_INTERFACE from 192.168.0.0/24 to any block in quick on EXTERNAL_INTERFACE from any to aaa.aaa.aaa.0/32 block in quick on EXTERNAL_INTERFACE from any to aaa.aaa.aaa.255/32 # block broadcast traffic from the internal network block in quick on INTERNAL_INTERFACE from any to bbb.bbb.bbb.0/32 block in quick on INTERNAL_INTERFACE from any to bbb.bbb.bbb.255/32 # pass traffic out from EXTERNAL_INTERFACE and from INTERNAL_NETWORK pass out quick on EXTERNAL_INTERFACE proto tcp/udp from \ BRIDGE2_EXTERNAL_IP/32 to any keep state pass out quick on EXTERNAL_INTERFACE proto icmp from \ BRIDGE2_EXTERNAL_IP/32 to any keep state pass out quick on EXTERNAL_INTERFACE proto tcp/udp from \ BRIDGE2_INTERNAL_NETWORK/24 to any keep state # pass IPSEC traffic for bridge0 and enc1 pass in quick proto esp from BRIDGE1_EXTERNAL_IP/32 to \ BRIDGE2_EXTERNAL_IP/32 pass out quick proto esp from BRIDGE2_EXTERNAL_IP/32 to \ BRIDGE1_EXTERNAL_IP/32 pass in quick on enc1 from BRIDGE1_INTERNAL_NETWORK/24 to \ BRIDGE2_INTERNAL_NETWORK/24 After configuring both bridges use the following command to flush IPF and restart it with the current ruleset: # ipf -Fa -f /etc/ipf.rules /Benefits of this Technique If you've stuck with the examples this far, you're likely to have a functioning IPSEC bridge on your hands. As far as client machines on either internal network know; they are on a LAN with every machine on the network (including machines remotely located on the other side of the VPN). You should find arp entries for all client machines on each bridge box. It should now be possible to install a WINS server (or Samba acting as WINS) on either side of the VPN and have all machines connect to it (thus establishing Network Neighborhood for all machines involved). Any IP-based protocol should function provided that said protocol does not mandate passing broadcast traffic (hence the use of WINS to establish NetBIOS ease-of-use). /Drawbacks not Readily Apparent You may have realized that all the machines on both sides of the VPN will need to share the same address space to route IP. As with a normal physical bridge; normal routing applies. Non-IP protocols *will* be transmitted across the VPN unless you include the brconfig blocknonip line in your configurations. The provided perl utility does *not* filter non-IP traffic by default. /In Closing Enjoy. Pampering Windows clients is, of course; only one use for an IPSEC bridge. --/Further Reading-Bibliography brconfig(8) vpn(8) ipf(5) Transparent Network Security Policy Enforcement [ http://www.thought.net/jason/bridgepaper ] Using IPSEC and Samba to integrate Windows Networks [ http://napalm.firest0rm.org/issue7.html#integ ] /Signed .-----------------------------------------------------------------------------. | | | _azure | | | `-----------------------------------------------------------------------------' EOF