@@ -490,16 +490,16 @@ def do_pf(port, dnsport, family, subnets, udp):
490490 filtering_rules = []
491491
492492 if subnets :
493- include_subnets = filter ( lambda s : not s [ 2 ], sorted ( subnets , reverse = True ))
494- if include_subnets :
495- tables . append ( ' table <include_subnets> {%s}' % ',' . join ([ "%s/%s" % ( n [ 3 ], n [ 1 ]) for n in include_subnets ]))
496- translating_rules . append ( 'rdr pass on lo0 proto tcp to <include_subnets> -> 127.0.0.1 port %r' % port )
497- filtering_rules . append ( 'pass out route-to lo0 inet proto tcp to <include_subnets> keep state' )
498-
499- exclude_subnets = filter ( lambda s : s [ 2 ], sorted ( subnets , reverse = True ))
500- if exclude_subnets :
501- tables .append ('table <exclude_subnets> {%s}' % ',' . join ([ "%s/%s" % ( n [ 3 ], n [ 1 ]) for n in exclude_subnets ]) )
502- filtering_rules .append ('pass out quick proto tcp from any to <exclude_subnets > keep state' )
493+ includes = []
494+ # If a given subnet is both included and excluded, list the exclusion
495+ # first; the table will ignore the second, opposite definition
496+ for f , swidth , sexclude , snet \
497+ in sorted ( subnets , key = lambda s : ( s [ 1 ], s [ 2 ]), reverse = True ):
498+ includes . append ( "%s%s/%s" % ( "!" if sexclude else "" , snet , swidth ))
499+
500+ tables . append ( 'table <forward_subnets> {%s}' % ',' . join ( includes ))
501+ translating_rules .append ('rdr pass on lo0 proto tcp to <forward_subnets> -> 127.0.0.1 port %r' % port )
502+ filtering_rules .append ('pass out route-to lo0 inet proto tcp to <forward_subnets > keep state' )
503503
504504 if dnsport :
505505 nslist = resolvconf_nameservers ()
0 commit comments