What is the minimal pf.conf for mount_smbfs to work?

I am trying to fix the following error:

Code:
mount_smbfs //user@server/share /mnt/share
mount_smbfs: can't get server address: syserr = Operation timed out

with the following pf.cof

Code:
ext_if="igb0"

tcp_pass_in= "{ ssh netbios-ssn netbios-ns netbios-dgm swat }"
udp_pass_in= "{ ssh netbios-ns netbios-ssn netbios-dgm }"

block in log
pass out all keep state
pass in on lo0 all

pass in on $ext_if proto tcp from any to any port $tcp_pass_in keep state
pass in on $ext_if proto udp from any to any port $udp_pass_in keep state

When I disable PF, there's no error.

Inspecting pflog shows that a netbios-ns response from the server was blocked:
Code:
00:00:02.275714 rule 0..16777216/0(match): block in on igb0: 192.168.1.2.137 > 192.168.1.1.38295: NBT UDP PAC                     KET(137): QUERY; POSITIVE; RESPONSE; UNICAST
where 192.168.1.1 is local machine and 192.168.1.2 is the server.

My understanding was that "keep state" in
Code:
pass out all keep state
should let the server response to the original local machine netbios name resolution request through. Am I wrong?

How should I change pf.conf for mount_smbfs to work?
 
Not related to the issue but this:
Code:
pass in on lo0 all
Should really be changed to:
Code:
set skip on lo0
 
If want to allow the server responses to queries initiated by the client then you should use a rule like this:

Code:
pass out quick on $ext_if inet proto udp from $ext_if to any port 137
. This works because by default the rules are stateful, so you do not need an additional rule to allow the answers in.
This is quite different from what you have ;)


As illustration a simple, but highly restrictive rule set for a workstation that allows you to browse the web:
Code:
ext_if = "re0"

web = "{ www https }"

block log all

pass out quick on $ext_if inet proto udp from $ext_if to any port domain 
pass out quick on $ext_if inet proto tcp from $ext_if to any port domain 
pass out quick on $ext_if inet proto tcp from $ext_if to any port $web

Try it and use # pfctl -vvsr:
Code:
@0 block drop log all
  [ Evaluations: 204       Packets: 58        Bytes: 3688        States: 0     ]
  [ Inserted: uid 0 pid 16234 State Creations: 0     ]
@1 pass out quick on re0 inet proto tcp from 192.168.222.20 to any port = 53 flags S/SA
  [ Evaluations: 204       Packets: 0         Bytes: 0           States: 0     ]
  [ Inserted: uid 0 pid 16234 State Creations: 0     ]
@2 pass out quick on re0 inet proto tcp from 192.168.222.20 to any port = 80 flags S/SA
  [ Evaluations: 72        Packets: 706       Bytes: 356606      States: 34    ]
  [ Inserted: uid 0 pid 16234 State Creations: 42    ]
@3 pass out quick on re0 inet proto tcp from 192.168.222.20 to any port = 443 flags S/SA
  [ Evaluations: 30        Packets: 0         Bytes: 0           States: 0     ]
  [ Inserted: uid 0 pid 16234 State Creations: 0     ]
@4 pass out quick on re0 inet proto udp from 192.168.222.20 to any port = 53
  [ Evaluations: 162       Packets: 206       Bytes: 17438       States: 94    ]
  [ Inserted: uid 0 pid 16234 State Creations: 104   ]

Or just the states with # pfctl -ss:
Code:
all tcp 192.168.222.20:22430 -> 23.66.243.172:80       FIN_WAIT_2:FIN_WAIT_2
all tcp 192.168.222.20:46581 -> 173.194.65.139:80       ESTABLISHED:ESTABLISHED
all tcp 192.168.222.20:19758 -> 54.230.129.21:80       FIN_WAIT_2:FIN_WAIT_2
all tcp 192.168.222.20:6122 -> 54.230.129.21:80       FIN_WAIT_2:FIN_WAIT_2
all tcp 192.168.222.20:28343 -> 173.194.65.148:80       ESTABLISHED:ESTABLISHED
Or more verbose
Code:
[cmd=#]pfctl -vvss[/cmd]
all udp 192.168.222.20:35584 -> 192.168.222.10:53       MULTIPLE:SINGLE
   age 00:00:04, expires in 00:00:26, 1:1 pkts, 61:100 bytes, rule 4
   id: 523c026a00000860 creatorid: 00df5049
all udp 192.168.222.20:35584 -> 192.168.222.10:53       MULTIPLE:SINGLE
   age 00:00:19, expires in 00:00:11, 1:1 pkts, 61:100 bytes, rule 4
   id: 523c026a00000860 creatorid: 00df5049
all udp 192.168.222.20:10063 -> 192.168.222.10:53       MULTIPLE:SINGLE
   age 00:00:03, expires in 00:00:27, 1:1 pkts, 61:100 bytes, rule 4
   id: 523c026a00000861 creatorid: 00df5049

Together with a "block log all" rule to deny all traffic by default and # tcpdump -eni pflog0 you should be able to figure out how to modify your ruleset ;)
 
J65nko said:
If want to allow the server responses to queries initiated by the client then you should use a rule like this:

Code:
pass out quick on $ext_if inet proto udp from $ext_if to any port 137
. This works because by default the rules are stateful, so you do not need an additional rule to allow the answers in.
This is quite different from what you have ;)

I've tried this rule, and I still get the same error with mount_smbfs while incoming UDP packets from server port 137 to local host external interface shown as blocked in pflog. I wonder what prevents PF from keeping state of the original NetBIOS request?
 
I do not have a suitable envirionment to verify this, but if indeed PF does not keep state on those NetBIOS name service requests you could use rules like this:
Code:
# --- incoming traffic
pass in quick on $ext_if inet proto udp from $server port 137 to $ext_if port >1023 no state 

# --- outgoing traffic
pass out quick on $ext_if inet proto udp from $ext_if port >1023 to $server port 137 no state
 
Few more details:

Here's the pf state:

Code:
# pfctl -ss
all udp 192.168.1.1:23189 -> 192.168.1.255:137       SINGLE:NO_TRAFFIC
all udp 192.168.1.255:137 <- 192.168.1.1:23189       NO_TRAFFIC:SINGLE

what does SINGLE:NO_TRAFFIC stand for?

Here're blocked replies:
Code:
#tcpdump -n -e -ttt -r /var/log/pflog
reading from file /var/log/pflog, link-type PFLOG (OpenBSD pflog file)
00:00:00.000000 rule 0..16777216/0(match): block in on igb0: 192.168.1.2.137 > 192.168.1.1.23189: NBT UDP PACKET(137): QUERY; POSITIVE; RESPONSE; UNICAST
 
tedjohnson said:
Code:
# pfctl -ss
all udp 192.168.1.1:23189 -> 192.168.1.255:137       SINGLE:NO_TRAFFIC
all udp 192.168.1.255:137 <- 192.168.1.1:23189       NO_TRAFFIC:SINGLE
These states use 192.168.1.255, probably the broadcast address of the local network, and and neither the 192.168.1.2 server IP , nor the 192.168.1.1 client address.

That is why 192.168.1.2.137 > 192.168.1.1.23189 is being blocked, because there is no such state. The only one using the same port numbers (192.168.1.1:23189 -> 192.168.1.255:137) uses a different destination address.

Please see my previous post, you probably missed it, for a workaround.
 
J65nko said:
These states use 192.168.1.255, probably the broadcast address of the local network, and and neither the 192.168.1.2 server IP , nor the 192.168.1.1 client address.

That is why 192.168.1.2.137 > 192.168.1.1.23189 is being blocked, because there is no such state. The only one using the same port numbers (192.168.1.1:23189 -> 192.168.1.255:137) uses a different destination address.

Please see my previous post, you probably missed it, for a workaround.

Thanks for explanation.

As far as workaround, I did, in fact, came up with similar rule
- leave a hole for any name resolution response traffic from broadcast-wide sub-net:
Code:
table <locals> { 192.168.1.0/24 }
pass in on $ext_if proto udp from <locals> port netbios-ns to $ext_if

I wonder if there is any way with PF to trigger a specific rule by a specific packet match, with a timeout on the rule? (i.e. make above rule active only after a name request was broadcast by local host, and then turn it off after short timeout?)
 
States created by UDP traffic are expired automatically just like the states created by TCP traffic. The settings that define the timeouts are udp.first, udp.single and udp.multiple. See pf.conf(5) for details.
 
kpa said:
States created by UDP traffic are expired automatically just like the states created by TCP traffic. The settings that define the timeouts are udp.first, udp.single and udp.multiple. See pf.conf(5) for details.

The problem is that though broadcast for NetBIOS name does create a state, the response is still blocked by PF, as outlined above.

I was wondering if one can have a pass rule triggered to turn on and off via a particular type of packet, a packet that is not part of the rule itself.
 
Back
Top