1010from helpers import log , debug1 , debug3 , islocal , Fatal , family_to_string , \
1111 resolvconf_nameservers
1212from fcntl import ioctl
13- from ctypes import c_char , c_uint8 , c_uint16 , c_uint32 , Union , Structure , sizeof , addressof , memmove
13+ from ctypes import c_char , c_uint8 , c_uint16 , c_uint32 , Union , Structure , \
14+ sizeof , addressof , memmove
1415
1516
1617# python doesn't have a definition for this
@@ -466,23 +467,28 @@ def do_wait():
466467 return do_wait
467468
468469
469- def pfctl (* args ):
470- argv = ['pfctl' ] + list (args )
471- debug1 ('>> %s\n ' % ' ' .join (argv ))
472- rv = ssubprocess .Popen (argv , stderr = ssubprocess .PIPE ).wait ()
473- if rv :
474- raise Fatal ('%r returned %d' % (argv , rv ))
470+ def pfctl (args , stdin = None ):
471+ argv = ['pfctl' ] + list (args .split (" " ))
472+ debug1 ('>> %s, stdin:%s\n ' % (' ' .join (argv ), stdin ))
473+
474+ p = ssubprocess .Popen (argv , stdin = ssubprocess .PIPE ,
475+ stdout = ssubprocess .PIPE ,
476+ stderr = ssubprocess .PIPE )
477+ o = p .communicate (stdin )
478+ if p .returncode :
479+ raise Fatal ('%r returned %d' % (argv , p .returncode ))
475480
481+ return o
482+
483+ _pf_started_by_sshuttle = False
476484
477485def do_pf (port , dnsport , family , subnets , udp ):
486+ global _pf_started_by_sshuttle
478487 tables = []
479488 translating_rules = []
480489 filtering_rules = []
481490
482491 if subnets :
483- pf_add_anchor_rule (PF_PASS , "sshuttle" )
484- pf_add_anchor_rule (PF_RDR , "sshuttle" )
485-
486492 include_subnets = filter (lambda s :not s [2 ], sorted (subnets , reverse = True ))
487493 if include_subnets :
488494 tables .append ('table <include_subnets> {%s}' % ',' .join (["%s/%s" % (n [3 ], n [1 ]) for n in include_subnets ]))
@@ -500,13 +506,23 @@ def do_pf(port, dnsport, family, subnets, udp):
500506 translating_rules .append ('rdr pass on lo0 proto udp to <dns_servers> port 53 -> 127.0.0.1 port %r' % dnsport )
501507 filtering_rules .append ('pass out route-to lo0 inet proto udp to <dns_servers> port 53 keep state' )
502508
503- pf_config_file = '/etc/pf-sshuttle.conf'
504- with open (pf_config_file , 'w+' ) as f :
505- f .write ('\n ' .join (tables + translating_rules + filtering_rules ) + '\n ' )
509+ rules = '\n ' .join (tables + translating_rules + filtering_rules ) + '\n '
506510
507- pfctl ('-E' , '-a' , 'sshuttle' , '-f' , pf_config_file )
511+ pf_status = pfctl ('-s all' )[0 ]
512+ if not '\n rdr-anchor "sshuttle" all\n ' in pf_status :
513+ pf_add_anchor_rule (PF_RDR , "sshuttle" )
514+ if not '\n anchor "sshuttle" all\n ' in pf_status :
515+ pf_add_anchor_rule (PF_PASS , "sshuttle" )
516+ if not 'INFO:\n Status: Enabled' in pf_status :
517+ pfctl ('-e' )
518+ _pf_started_by_sshuttle = True
519+
520+ pfctl ('-a sshuttle -f /dev/stdin' , rules )
508521 else :
509- pfctl ('-a' , 'sshuttle' , '-F' , 'all' )
522+ pfctl ('-a sshuttle -F all' )
523+
524+ if _pf_started_by_sshuttle :
525+ pfctl ('-d' )
510526
511527
512528def program_exists (name ):
0 commit comments