Why would you want a Bonjour Gateway? Because you have more than 1 network and you want to have Bonjour devices be able to talk to each other even though they aren’t on the same network.
For example, at work, you have Apple TVs that are on one network, and guests that connect to a different network and they need to be able to present using the Apple TV. Why do I keep saying Bonjour instead of mDNS? They are, for the purposes of this article, equivalent, and I have to pick one. Since its more likely that people of an Apple bent will be interested in this, I’m using the Apple terminology.
Prerequisites
When building your machine (physical or virtual), you will either need 2 NICs (network interface card), or the ability to use a trunk port and multiple VLANs. If you choose the latter, don’t forget to adjust these settings as you go.
FreeBSD Install
Standard FreeBSD install. Used pkg to install the following:
1accessibility/atk
2converters/libiconv
3databases/gdbm
4devel/dbus
5devel/dbus-glib
6devel/gettext-runtime
7devel/gettext-tools
8devel/glib20
9devel/gobject-introspection
10devel/icu
11devel/libdaemon
12devel/libdevq
13devel/libedit
14devel/libevent2
15devel/libffi
16devel/libglade2
17devel/libpciaccess
18devel/libpthread-stubs
19devel/llvm37
20devel/pcre
21devel/pkgconf
22dns/libidn
23editors/vim
24emulators/open-vm-tools-nox11
25emulators/tpm-emulator
26graphics/cairo
27graphics/gbm
28graphics/gdk-pixbuf2
29graphics/graphite2
30graphics/gtk-update-icon-cache
31graphics/jasper
32graphics/jbigkit
33graphics/jpeg-turbo
34graphics/libEGL
35graphics/libGL
36graphics/libdrm
37graphics/libglapi
38graphics/png
39graphics/tiff
40lang/perl5.20
41lang/python
42lang/python2
43lang/python27
44math/gmp
45misc/hicolor-icon-theme
46misc/pciids
47misc/shared-mime-info
48net/avahi
49net/avahi-app
50net/avahi-autoipd
51net/avahi-gtk
52net/avahi-header
53net/libdnet
54ports-mgmt/dialog4ports
55ports-mgmt/pkg
56print/cups
57print/freetype2
58print/harfbuzz
59print/indexinfo
60print/libpaper
61security/ca_root_nss
62security/gnutls
63security/libtasn1
64security/nettle
65security/p11-kit
66security/sudo
67security/trousers
68sysutils/gnome_subr
69sysutils/tmux
70textproc/expat2
71textproc/libxml2
72textproc/xmlcatmgr
73x11-fonts/dejavu
74x11-fonts/encodings
75x11-fonts/font-bh-ttf
76x11-fonts/font-misc-ethiopic
77x11-fonts/font-misc-meltho
78x11-fonts/font-util
79x11-fonts/fontconfig
80x11-fonts/libXft
81x11-fonts/libfontenc
82x11-fonts/mkfontdir
83x11-fonts/mkfontscale
84x11-fonts/xorg-fonts-truetype
85x11-toolkits/gtk20
86x11-toolkits/libXt
87x11-toolkits/pango
88x11/compositeproto
89x11/damageproto
90x11/dri2proto
91x11/fixesproto
92x11/glproto
93x11/inputproto
94x11/kbproto
95x11/libICE
96x11/libSM
97x11/libX11
98x11/libXau
99x11/libXcomposite
100x11/libXcursor
101x11/libXdamage
102x11/libXdmcp
103x11/libXext
104x11/libXfixes
105x11/libXi
106x11/libXinerama
107x11/libXrandr
108x11/libXrender
109x11/libXv
110x11/libXvMC
111x11/libXxf86vm
112x11/libxcb
113x11/libxshmfence
114x11/pixman
115x11/randrproto
116x11/renderproto
117x11/videoproto
118x11/xcb-util
119x11/xcb-util-renderutil
120x11/xextproto
121x11/xf86vidmodeproto
122x11/xineramaproto
123x11/xproto
rc.conf settings:
1hostname="bonjour-bridge.cmhome"
2ifconfig_em0="DHCP"
3ifconfig_em1="inet 198.18.9.10/24"
4ifconfig_em0_ipv6="inet6 accept_rtadv"
5ifconfig_em1_ipv6="inet6 fc00:101:ca7:9::10/64"
6sshd_enable="YES"
7ntpd_enable="YES"
8ntpd_sync_on_start="YES"
9dumpdev="AUTO"
10vmware_guest_vmblock_enable="YES"
11vmware_guest_vmhgfs_enable="YES"
12vmware_guest_vmmemctl_enable="YES"
13vmware_guest_vmxnet_enable="YES"
14vmware_guestd_enable="YES"
15avahi_daemon_enable="YES"
16dbus_enable="YES"
17pf_enable="YES"
18pflog_enable="YES"
I picked a static IP on one side, and left the other DHCP. Doesn’t really matter how you do it. Could be static on both sides, probably don’t want to do DHCP on both sides unless you ensure you don’t pick up 2 default routes.
Note: If you aren’t in a virtual machine, skip the open-vm-tools-nox11 pkg, and the vmware-* sysrc knobs.
Configuring Avahi
Literally, the only line I changed in avahi-daemon.conf was (uncomment):
1enable-reflector=no
Enable Avahi (and DBUS):
1sysrc avahi_daemon_enable=YES
2sysrc dbus_enable=YES
Start the services:
1service avahi-daemon start
2service dbus start
You should see something like the following, indicating the process are running:
1[louisk@bonjour-bridge avahi 34 ]$ ps ax | egrep 'dbus|avahi'
2 670 - Is 0:00.00 /usr/local/bin/dbus-daemon --system
3 674 - S 0:03.21 avahi-daemon: running [bonjour-bridge.local] (avahi-dae
4[louisk@bonjour-bridge avahi 35 ]$
Configuring PF
I wanted to block essentially everything but Bonjour (mDNS).
1#
2# Based on Calomel.org pf.conf
3#
4################ FreeBSD pf.conf ##########################
5# Required order: options, normalization, queueing, translation, filtering.
6# Note: translation rules are first match while filter rules are last match.
7################ Macros ###################################
8
9### Interfaces ###
10 ExtIf ="em0"
11 IntIf ="em1"
12
13### Queues, States and Types ###
14 IcmpPing ="icmp-type 8 code 0"
15 SshQueue ="(ssh_bulk, ssh_login)"
16 SynState ="flags S/UAPRSF synproxy state"
17 TcpState ="flags S/UAPRSF modulate state"
18 UdpState ="keep state"
19
20### Ports ###
21 AntiScanPort="{23:79, 6000:8000}"
22 BlockNoLogPort="{17500,445,136:139}"
23
24### Stateful Tracking Options (STO) ###
25 OpenSTO ="(max 500, source-track rule, max-src-conn 10, max-src-nodes 256)"
26 SshSTO ="(max 10, source-track rule, max-src-conn 10, max-src-nodes 10, max-src-conn-rate 5/3, overload <BLOCKTEMP> flush global)"
27 WebSTO ="(max 100, source-track rule, max-src-conn 10, max-src-nodes 10, max-src-conn-rate 5/10, overload <BLOCKTEMP> flush global)"
28 AntiScanSTO ="(max 10, source-track rule, max-src-conn 1, max-src-nodes 10, max-src-conn-rate 1/60, overload <BLACKTEMP> flush global)"
29
30### Tables ###
31 table <BLOCKTEMP> counters
32
33################ Options ######################################################
34### Misc Options
35 set skip on lo
36 set debug urgent
37 set block-policy drop
38 set loginterface $ExtIf
39 set loginterface $IntIf
40 set state-policy if-bound
41 set fingerprints "/etc/pf.os"
42 set ruleset-optimization none
43
44### Timeout Options
45 set optimization normal
46 set timeout { tcp.closing 60, tcp.established 7200}
47
48################ Normalization ###############################################
49# set-tos 0x1c is Maximize-Reliability + Minimize-Delay + Maximize-Throughput
50scrub out log on $ExtIf all random-id min-ttl 15 set-tos 0x1c fragment reassemble
51scrub out log on $IntIf all random-id min-ttl 15 set-tos 0x1c fragment reassemble
52
53################ Filtering ###################################################
54# Rules are best (closest) match. Notice we optimized the rules so external
55# interface parsing is first followed by the internal interface.
56
57### Things to block silently
58 block drop in quick on $ExtIf inet proto tcp from any to any port $BlockNoLogPort
59 block drop in quick on $ExtIf inet proto udp from any to any port $BlockNoLogPort
60
61### $ExtIf block abusive hosts in temp tables
62 block drop in log quick on $ExtIf from <BLOCKTEMP> to any
63 block drop in log quick on $IntIf from <BLOCKTEMP> to any
64
65### $ExtIf default block with drop
66 block drop in log on $ExtIf
67 block drop in log on $IntIf
68
69### $ExtIf $IntIf inbound
70# DHCP
71 pass in on $ExtIf inet proto tcp from any to any port 67:68 $UdpState $OpenSTO
72 pass in on $ExtIf inet proto udp from any to any port 67:68 $UdpState $OpenSTO
73 pass in on $ExtIf inet proto tcp from !($ExtIf) to 224.0.0.251 port 5353:5354 $UdpState $OpenSTO
74 pass in on $ExtIf inet proto udp from !($ExtIf) to 224.0.0.251 port 5353:5354 $UdpState $OpenSTO
75 pass in on $IntIf inet proto tcp from !($IntIf) to 224.0.0.251 port 5353:5354 $UdpState $OpenSTO
76 pass in on $IntIf inet proto udp from !($IntIf) to 224.0.0.251 port 5353:5354 $UdpState $OpenSTO
77 pass in on $ExtIf inet proto tcp from !($ExtIf) to ($ExtIf) port ssh $TcpState $SshSTO
78 pass in on $ExtIf inet6 proto tcp from !($ExtIf) to ($ExtIf) port ssh $TcpState $SshSTO
79 pass in on $ExtIf inet proto icmp from !($ExtIf) to any $UdpState $OpenSTO
80 pass in on $IntIf inet proto icmp from !($IntIf) to any $UdpState $OpenSTO
81 pass in on $ExtIf inet6 proto icmp6 from !($ExtIf) to any $UdpState $OpenSTO
82 pass in on $IntIf inet6 proto icmp6 from !($IntIf) to any $UdpState $OpenSTO
83 pass in log on $ExtIf inet proto tcp from any to any port $AntiScanPort $SynState $AntiScanSTO
84 pass in log on $IntIf inet proto tcp from any to any port $AntiScanPort $SynState $AntiScanSTO
85 pass in log on $ExtIf inet6 proto tcp from any to any port $AntiScanPort $SynState $AntiScanSTO
86 pass in log on $IntIf inet6 proto tcp from any to any port $AntiScanPort $SynState $AntiScanSTO
87
88### $ExtIf $IntIf outbound
89# DHCP
90 pass out on $ExtIf inet proto tcp from any to any port 67:68 $UdpState $OpenSTO
91 pass out on $ExtIf inet proto udp from any to any port 67:68 $UdpState $OpenSTO
92# MDNS
93 pass out on $ExtIf inet proto tcp from ($ExtIf) to 224.0.0.251 port 5353:5354 $UdpState $OpenSTO
94 pass out on $ExtIf inet proto udp from ($ExtIf) to 224.0.0.251 port 5353:5354 $UdpState $OpenSTO
95 pass out on $IntIf inet proto tcp from ($ExtIf) to 224.0.0.251 port 5353:5354 $UdpState $OpenSTO
96 pass out on $IntIf inet proto udp from ($ExtIf) to 224.0.0.251 port 5353:5354 $UdpState $OpenSTO
97
98 pass out on $ExtIf inet proto tcp from ($ExtIf) to any $TcpState $OpenSTO
99 pass out on $IntIf inet proto tcp from ($ExtIf) to any $TcpState $OpenSTO
100 pass out on $ExtIf inet6 proto tcp from ($ExtIf) to any $TcpState $OpenSTO
101 pass out on $IntIf inet6 proto tcp from ($ExtIf) to any $TcpState $OpenSTO
102 pass out on $ExtIf inet proto udp from ($ExtIf) to any $UdpState $OpenSTO
103 pass out on $IntIf inet proto udp from ($ExtIf) to any $UdpState $OpenSTO
104 pass out on $ExtIf inet6 proto udp from ($ExtIf) to any $UdpState $OpenSTO
105 pass out on $IntIf inet6 proto udp from ($ExtIf) to any $UdpState $OpenSTO
106 pass out on $ExtIf inet proto icmp from ($ExtIf) to any $UdpState $OpenSTO
107 pass out on $IntIf inet proto icmp from ($ExtIf) to any $UdpState $OpenSTO
108 pass out on $ExtIf inet6 proto icmp6 from ($ExtIf) to any $UdpState $OpenSTO
109 pass out on $IntIf inet6 proto icmp6 from ($ExtIf) to any $UdpState $OpenSTO
110
111############# END of FreeBSD pf.conf #######################
Enable pf and pflog with:
1sysrc pf_enable=YES
2sysrc pflog_enable=YES
Start the services (starting pf will kill any remote sessions such as ssh, but if things are configured properly, you will not be locked out, just existing sessions are terminated):
1service pflog start
2service pf start
You can check that pf is running by doing:
1pfctl -s rules
You should see output like:
1[louisk@bonjour-bridge avahi 35 ]$ sudo pfctl -s rules
2scrub out log on em0 all random-id min-ttl 15 set-tos 0x1c fragment reassemble
3scrub out log on em1 all random-id min-ttl 15 set-tos 0x1c fragment reassemble
4block drop in quick on em0 inet proto tcp from any to any port = 17500
5block drop in quick on em0 inet proto tcp from any to any port = microsoft-ds
6block drop in quick on em0 inet proto tcp from any to any port 136:139
7block drop in quick on em0 inet proto udp from any to any port = 17500
8block drop in quick on em0 inet proto udp from any to any port = microsoft-ds
9block drop in quick on em0 inet proto udp from any to any port 136:139
10block drop in log quick on em0 from <BLOCKTEMP> to any
11block drop in log quick on em1 from <BLOCKTEMP> to any
12block drop in log on em0 all
13block drop in log on em1 all
14pass in on em0 inet proto tcp from any to any port 67:68 flags S/SA keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
15pass in on em0 inet proto udp from any to any port 67:68 keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
16pass in on em0 inet proto tcp from ! (em0) to 224.0.0.251 port 5353:5354 flags S/SA keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
17pass in on em0 inet proto udp from ! (em0) to 224.0.0.251 port 5353:5354 keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
18pass in on em1 inet proto tcp from ! (em1) to 224.0.0.251 port 5353:5354 flags S/SA keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
19pass in on em1 inet proto udp from ! (em1) to 224.0.0.251 port 5353:5354 keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
20pass in on em0 inet proto tcp from ! (em0) to (em0) port = ssh flags S/FSRPAU modulate state (max 10, source-track rule, max-src-conn 10, max-src-conn-rate 5/3, max-src-nodes 10, overload <BLOCKTEMP> flush global, if-bound, adaptive.start 6, adaptive.end 12, src.track 3)
21pass in on em0 inet6 proto tcp from ! (em0) to (em0) port = ssh flags S/FSRPAU modulate state (max 10, source-track rule, max-src-conn 10, max-src-conn-rate 5/3, max-src-nodes 10, overload <BLOCKTEMP> flush global, if-bound, adaptive.start 6, adaptive.end 12, src.track 3)
22pass in on em0 inet proto icmp from ! (em0) to any keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
23pass in on em1 inet proto icmp from ! (em1) to any keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
24pass in on em0 inet6 proto ipv6-icmp from ! (em0) to any keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
25pass in on em1 inet6 proto ipv6-icmp from ! (em1) to any keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
26pass in log on em0 inet proto tcp from any to any port 23:79 flags S/FSRPAU synproxy state (max 10, source-track rule, max-src-conn 1, max-src-conn-rate 1/60, max-src-nodes 10, overload <BLACKTEMP> flush global, if-bound, adaptive.start 6, adaptive.end 12, src.track 60)
27pass in log on em0 inet proto tcp from any to any port 6000:8000 flags S/FSRPAU synproxy state (max 10, source-track rule, max-src-conn 1, max-src-conn-rate 1/60, max-src-nodes 10, overload <BLACKTEMP> flush global, if-bound, adaptive.start 6, adaptive.end 12, src.track 60)
28pass in log on em1 inet proto tcp from any to any port 23:79 flags S/FSRPAU synproxy state (max 10, source-track rule, max-src-conn 1, max-src-conn-rate 1/60, max-src-nodes 10, overload <BLACKTEMP> flush global, if-bound, adaptive.start 6, adaptive.end 12, src.track 60)
29pass in log on em1 inet proto tcp from any to any port 6000:8000 flags S/FSRPAU synproxy state (max 10, source-track rule, max-src-conn 1, max-src-conn-rate 1/60, max-src-nodes 10, overload <BLACKTEMP> flush global, if-bound, adaptive.start 6, adaptive.end 12, src.track 60)
30pass in log on em0 inet6 proto tcp from any to any port 23:79 flags S/FSRPAU synproxy state (max 10, source-track rule, max-src-conn 1, max-src-conn-rate 1/60, max-src-nodes 10, overload <BLACKTEMP> flush global, if-bound, adaptive.start 6, adaptive.end 12, src.track 60)
31pass in log on em0 inet6 proto tcp from any to any port 6000:8000 flags S/FSRPAU synproxy state (max 10, source-track rule, max-src-conn 1, max-src-conn-rate 1/60, max-src-nodes 10, overload <BLACKTEMP> flush global, if-bound, adaptive.start 6, adaptive.end 12, src.track 60)
32pass in log on em1 inet6 proto tcp from any to any port 23:79 flags S/FSRPAU synproxy state (max 10, source-track rule, max-src-conn 1, max-src-conn-rate 1/60, max-src-nodes 10, overload <BLACKTEMP> flush global, if-bound, adaptive.start 6, adaptive.end 12, src.track 60)
33pass in log on em1 inet6 proto tcp from any to any port 6000:8000 flags S/FSRPAU synproxy state (max 10, source-track rule, max-src-conn 1, max-src-conn-rate 1/60, max-src-nodes 10, overload <BLACKTEMP> flush global, if-bound, adaptive.start 6, adaptive.end 12, src.track 60)
34pass out on em0 inet proto tcp from any to any port 67:68 flags S/SA keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
35pass out on em0 inet proto udp from any to any port 67:68 keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
36pass out on em0 inet proto tcp from (em0) to 224.0.0.251 port 5353:5354 flags S/SA keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
37pass out on em0 inet proto udp from (em0) to 224.0.0.251 port 5353:5354 keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
38pass out on em1 inet proto tcp from (em0) to 224.0.0.251 port 5353:5354 flags S/SA keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
39pass out on em1 inet proto udp from (em0) to 224.0.0.251 port 5353:5354 keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
40pass out on em0 inet proto tcp from (em0) to any flags S/FSRPAU modulate state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
41pass out on em1 inet proto tcp from (em0) to any flags S/FSRPAU modulate state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
42pass out on em0 inet6 proto tcp from (em0) to any flags S/FSRPAU modulate state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
43pass out on em1 inet6 proto tcp from (em0) to any flags S/FSRPAU modulate state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
44pass out on em0 inet proto udp from (em0) to any keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
45pass out on em1 inet proto udp from (em0) to any keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
46pass out on em0 inet6 proto udp from (em0) to any keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
47pass out on em1 inet6 proto udp from (em0) to any keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
48pass out on em0 inet proto icmp from (em0) to any keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
49pass out on em1 inet proto icmp from (em0) to any keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
50pass out on em0 inet6 proto ipv6-icmp from (em0) to any keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
51pass out on em1 inet6 proto ipv6-icmp from (em0) to any keep state (max 500, source-track rule, max-src-conn 10, max-src-nodes 256, if-bound, adaptive.start 300, adaptive.end 600)
52[louisk@bonjour-bridge avahi 36 ]$
If you need to debug the firewall rules, you can run tcpdump against pflog0 and see whats getting blocked.
Summary
You should now be able to have your (as an example) Apple TV on one network and your phone/computer on another network and be able to use AirPlay. The Bonjour Gateway will block incoming traffic that isn’t part of mDNS, while allowing your airplay to function as expected.
Comments