I'm trying to put together a firewall for our DMZ and internal network. For some reason, a server in the DMZ can only hit the external DNS server if it has keep state on the DMZ interface. Basically the following (relvant extract) blocks access:
ext_if = "vr0" dmz_if = "em0" dmz_tcp_services_out = "{ http, https, ftp, ntp, domain }" dmz_tcp_services_in = "{ http, https, ssh }" dmz_udp_services_in = "{ ntp }" dmz_udp_services_out = "{ domain }" webserv2_dmz_ad = "{ 10.0.0.4 }" webserv2_ext_ad= "..." tcp_opts = "modulate state" # gave up on synproxy state udp_opts = "keep state" icmp_opts = "keep state" nat_proto = "{ tcp, udp, icmp }" scrub all reassemble tcp scrub in all fragment reassemble scrub out all random-id nat on $ext_if proto $nat_proto \ from $webserv2_dmz_ad -> $webserv2_ext_ad rdr on { $ext_if, $int_if } proto tcp \ from any to $webserv2_ext_ad port www -> $webserv2_dmz_ad port www block in log (all) all block out log (all) all antispoof log quick for $antispoof_if pass out on $ext_if proto tcp \ from any to any $tcp_opts pass out on $ext_if proto udp \ from any to any $udp_opts pass out on $ext_if inet proto icmp \ from any to any $icmp_opts pass in on $dmz_if proto tcp \ from $dmz_ad to any port $dmz_tcp_services_out #$tcp_opts pass in on $dmz_if proto udp \ from $dmz_ad to any port $dmz_udp_services_out #$udp_opts pass in on $dmz_if proto icmp \ from $dmz_ad to any #$udp_opts Call dig with this setup and it times out; uncomment the options (modulate/keep) state and you get a DNS result. I was under the impression that the state should be created as the packets leave $ext_if, so why is it necessary to put a state option in the DMZ interface rules? Hope someone can clear this up Thanks Ashley -- "If you do it the stupid way, you will have to do it again" - Gregory Chudnovsky