def main(): s = 'FWLite ' + __version__ if gevent: s += ' with gevent %s' % gevent.__version__ logging.info(s) conf = config.conf Timer(10, updater, (conf, )).start() d = {'http': '127.0.0.1:%d' % conf.listen[1], 'https': '127.0.0.1:%d' % conf.listen[1]} urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler(d))) for i, level in enumerate(list(conf.userconf.dget('fgfwproxy', 'profile', '13'))): server = ThreadingHTTPServer((conf.listen[0], conf.listen[1] + i), ProxyHandler, conf=conf, level=int(level)) t = Thread(target=server.serve_forever) t.start() if conf.userconf.dgetbool('dns', 'enable', False): try: listen = parse_hostport(conf.userconf.dget('dns', 'listen', '127.0.0.1:53')) from dnsserver import Resolver, UDPDNSServer, DNSHandler, TCPDNSServer r = Resolver(conf.resolver) server = UDPDNSServer(listen, DNSHandler, r) t2 = Thread(target=server.serve_forever) t2.start() server = TCPDNSServer(listen, DNSHandler, r) t2 = Thread(target=server.serve_forever) t2.start() except Exception as e: logging.error(repr(e)) logging.error(traceback.format_exc() + '\n') conf.stdout() t.join()
def do_GET(self): noxff = False if isinstance(self.path, bytes): self.path = self.path.decode('latin1') if self.path.lower().startswith('ftp://'): return self.send_error(504) # transparent proxy if self.path.startswith('/') and 'Host' in self.headers: self.path = 'http://%s%s' % (self.headers['Host'], self.path) if self.path.startswith('/'): return self.send_error(403) # redirector new_url = REDIRECTOR.get(self.path) if new_url: logging.debug('redirecting to %s' % new_url) if new_url.isdigit() and 400 <= int(new_url) < 600: return self.send_error(int(new_url)) elif new_url in conf.parentdict.keys(): self._proxylist = [new_url] elif new_url.lower() == 'noxff': noxff = True else: return self.redirect(new_url) if 'Host' not in self.headers: self.headers['Host'] = urlparse.urlparse(self.path).netloc if 'ss-realip' in self.headers: # should exist in first request only self.ssrealip = self.headers['ss-realip'] del self.headers['ss-realip'] if 'ss-client' in self.headers: # should exist in first request only self.ssclient = self.headers['ss-client'] del self.headers['ss-client'] self.requesthost = parse_hostport(self.headers['Host'], 80) if self._request_localhost(self.requesthost): if ip_address(self.client_address[0]).is_loopback and self.requesthost[1] in (conf.listen[1], conf.listen[1] + 1): self.send_response(200) msg = 'Hello World !' self.send_header('Content-type', 'text/html') self.send_header('Content-Length', str(len(msg))) self.send_header('Connection', 'keep_alive') self.end_headers() # Send the html message self.wfile.write(msg) return if not ip_address(self.client_address[0]).is_loopback: return self.send_error(403) self.shortpath = '%s%s' % (self.path.split('?')[0], '?' if len(self.path.split('?')) > 1 else '') if conf.xheaders and self.ssrealip: ipl = [ip.strip() for ip in self.headers.get('X-Forwarded-For', '').split(',') if ip.strip()] ipl.append(self.ssrealip) self.headers['X-Forwarded-For'] = ', '.join(ipl) if noxff: del self.headers['X-Forwarded-For'] self._do_GET()
def __init__(self, serverinfo, RequestHandlerClass, bind_and_activate=True): self.serverinfo = serverinfo p = urlparse.urlparse(serverinfo) encrypt.check(p.password, p.username) self.key, self.method = p.password, p.username self.aports = [int(k) for k in urlparse.parse_qs(p.query).get('ports', [''])[0].split(',') if k.isdigit()] reverse = urlparse.parse_qs(p.query).get('reverse', [''])[0] self.reverse = parse_hostport(reverse) if reverse else None addrs = getaddrinfo(p.hostname, p.port) if not addrs: raise ValueError('cant resolve listen address') self.address_family = addrs[0][0] server_address = (p.hostname, p.port) SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate=bind_and_activate)
def match(self, url, host=None, domain_only=False): if host is None: if '://' in url: host = urlparse.urlparse(url).hostname else: # www.google.com:443 host = parse_hostport(url)[0] if self._listmatch(self.excludes, url): return False if self._domainmatch(host) is not None: return self._domainmatch(host) if domain_only: return None if url.startswith(self.url_startswith): return True if self._fastmatch(url): return True if self._listmatch(self.matches, url): return True
def match(self, url, host=None, domain_only=False): if host is None: if '://' in url: host = urllib.parse.urlparse(url).hostname else: # www.google.com:443 host = parse_hostport(url)[0] if '://' not in url: url = 'https://%s/' % host if self._listmatch(self.excludes, url): return False if self._domainmatch(host) is not None: return self._domainmatch(host) if domain_only: return None if self._fastmatch(url): return True if self._listmatch(self.slow, url): return True return None
def __init__(self, serverinfo, forward, RequestHandlerClass, bind_and_activate=True): self.serverinfo = serverinfo self.forward = set(forward) p = urlparse.urlparse(serverinfo) if p.scheme == 'ss': self.PSK, self.method = p.password, p.username elif p.scheme == 'hxs': self.PSK = urlparse.parse_qs(p.query).get('PSK', [''])[0] self.method = urlparse.parse_qs(p.query).get( 'method', [DEFAULT_METHOD])[0] else: raise ValueError('bad serverinfo: {}'.format(self.serverinfo)) q = urlparse.parse_qs(p.query) proxy = q.get('proxy', [''])[0] self.proxy = parse_hostport(proxy) if proxy else None self.server = q.get('UA', ['nginx/1.2.2'])[0] self.hash_algo = q.get('hash', [DEFAULT_HASH])[0].upper() self.ss = self.PSK and q.get('ss', ['1'])[0] == '1' addrs = socket.getaddrinfo(p.hostname, p.port) if not addrs: raise ValueError('cant resolve listen address') self.address_family = addrs[0][0] server_address = (p.hostname, p.port) SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate=bind_and_activate)
def __init__(self): self.logger = logging.getLogger('FW_Lite') self.version = SConfigParser() self.userconf = SConfigParser() self.reload() self.UPDATE_INTV = 6 self.timeout = self.userconf.dgetint('fgfwproxy', 'timeout', 4) ParentProxy.DEFAULT_TIMEOUT = self.timeout self.parentlist = ParentProxyList() self.HOSTS = defaultdict(list) self.GUI = '-GUI' in sys.argv self.rproxy = self.userconf.dgetbool('fgfwproxy', 'rproxy', False) listen = self.userconf.dget('fgfwproxy', 'listen', '8118') if listen.isdigit(): self.listen = ('127.0.0.1', int(listen)) else: self.listen = (listen.rsplit(':', 1)[0], int(listen.rsplit(':', 1)[1])) try: self.local_ip = set(socket.gethostbyname_ex(socket.gethostname())[2]) except: try: csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) csock.connect(('8.8.8.8', 53)) (addr, port) = csock.getsockname() csock.close() self.local_ip = set([addr]) except socket.error: self.local_ip = set(['127.0.0.1']) ip = self.local_ip.pop() self.local_ip.add(ip) self.PAC = '''\ function FindProxyForURL(url, host) { if (isPlainHostName(host) || host.indexOf('127.') == 0 || host.indexOf('192.168.') == 0 || host.indexOf('10.') == 0 || shExpMatch(host, 'localhost.*')) { return 'DIRECT'; } return "PROXY %s:%s; DIRECT";}''' % (ip, self.listen[1]) if self.userconf.dget('fgfwproxy', 'pac', ''): if os.path.isfile(self.userconf.dget('fgfwproxy', 'pac', '')): self.PAC = open(self.userconf.dget('fgfwproxy', 'pac', '')).read() else: self.PAC = '''\ function FindProxyForURL(url, host) { if (isPlainHostName(host) || host.indexOf('127.') == 0 || host.indexOf('192.168.') == 0 || host.indexOf('10.') == 0 || shExpMatch(host, 'localhost.*')) { return 'DIRECT'; } return "PROXY %s; DIRECT";}''' % self.userconf.dget('fgfwproxy', 'pac', '') self.PAC = self.PAC.encode() if self.userconf.dget('FGFW_Lite', 'logfile', ''): path = self.userconf.dget('FGFW_Lite', 'logfile', '') dirname = os.path.dirname(path) if dirname and not os.path.exists(dirname): os.makedirs(dirname) formatter = logging.Formatter('FW-Lite %(asctime)s %(levelname)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S') hdlr = logging.handlers.RotatingFileHandler(path, maxBytes=1048576, backupCount=5) hdlr.setFormatter(formatter) self.logger.addHandler(hdlr) self.region = set(x.upper() for x in self.userconf.dget('fgfwproxy', 'region', '').split('|') if x.strip()) self.profiles = len(self.userconf.dget('fgfwproxy', 'profile', '13')) self.xheaders = self.userconf.dgetbool('fgfwproxy', 'xheaders', False) if self.userconf.dget('fgfwproxy', 'parentproxy', ''): self.addparentproxy('direct', '%s 0' % self.userconf.dget('fgfwproxy', 'parentproxy', '')) self.addparentproxy('local', 'direct 100') else: self.addparentproxy('direct', 'direct 0') ParentProxy.set_via(self.parentlist.direct) for k, v in self.userconf.items('parents'): if '6Rc59g0jFlTppvel' in v: self.userconf.remove_option('parents', k) self.confsave() continue self.addparentproxy(k, v) if not self.rproxy and len([k for k in self.parentlist.httpsparents() if k.httpspriority < 100]) == 0: self.logger.warning('No parent proxy available!') self.maxretry = self.userconf.dgetint('fgfwproxy', 'maxretry', 4) def addhost(host, ip): try: ipo = ip_address(ip) if isinstance(ipo, IPv4Address): self.HOSTS[host].append((2, ip)) else: self.HOSTS[host].append((10, ip)) except Exception: self.logging.warning('unsupported host: %s' % ip) for host, ip in self.userconf.items('hosts'): addhost(host, ip) if os.path.isfile('./fgfw-lite/hosts'): for line in open('./fgfw-lite/hosts'): line = line.strip() if line and not line.startswith('#'): try: ip, host = line.split() addhost(host, ip) except Exception as e: self.logger.warning('%s %s' % (e, line)) self.localdns = parse_hostport(self.userconf.dget('dns', 'localdns', '8.8.8.8:53' if self.rproxy else '223.5.5.5:53')) self.remotedns = self.localdns if self.rproxy else parse_hostport(self.userconf.dget('dns', 'remotedns', '208.67.222.222:5353')) self.REDIRECTOR = redirector(self) self.PARENT_PROXY = get_proxy(self) self.resolver = resolver.get_resolver(self.localdns, self.remotedns, ParentProxy('self', 'http://127.0.0.1:%d' % self.listen[1]), self.PARENT_PROXY.force)
def __init__(self): self.logger = logging.getLogger('FW_Lite') self.version = SConfigParser() self.userconf = SConfigParser() self.reload() self.UPDATE_INTV = 6 self.timeout = self.userconf.dgetint('fgfwproxy', 'timeout', 4) ParentProxy.DEFAULT_TIMEOUT = self.timeout self.parentlist = ParentProxyList() self.HOSTS = defaultdict(list) self.GUI = '-GUI' in sys.argv self.rproxy = self.userconf.dgetbool('fgfwproxy', 'rproxy', False) listen = self.userconf.dget('fgfwproxy', 'listen', '8118') if listen.isdigit(): self.listen = ('127.0.0.1', int(listen)) else: self.listen = (listen.rsplit(':', 1)[0], int(listen.rsplit(':', 1)[1])) try: self.local_ip = set( socket.gethostbyname_ex(socket.gethostname())[2]) except: try: csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) csock.connect(('8.8.8.8', 53)) (addr, port) = csock.getsockname() csock.close() self.local_ip = set([addr]) except socket.error: self.local_ip = set(['127.0.0.1']) ip = self.local_ip.pop() self.local_ip.add(ip) self.PAC = '''\ function FindProxyForURL(url, host) { if (isPlainHostName(host) || host.indexOf('127.') == 0 || host.indexOf('192.168.') == 0 || host.indexOf('10.') == 0 || shExpMatch(host, 'localhost.*')) { return 'DIRECT'; } return "PROXY %s:%s; DIRECT";}''' % (ip, self.listen[1]) if self.userconf.dget('fgfwproxy', 'pac', ''): if os.path.isfile(self.userconf.dget('fgfwproxy', 'pac', '')): self.PAC = open(self.userconf.dget('fgfwproxy', 'pac', '')).read() else: self.PAC = '''\ function FindProxyForURL(url, host) { if (isPlainHostName(host) || host.indexOf('127.') == 0 || host.indexOf('192.168.') == 0 || host.indexOf('10.') == 0 || shExpMatch(host, 'localhost.*')) { return 'DIRECT'; } return "PROXY %s; DIRECT";}''' % self.userconf.dget('fgfwproxy', 'pac', '') self.PAC = self.PAC.encode() if self.userconf.dget('FGFW_Lite', 'logfile', ''): path = self.userconf.dget('FGFW_Lite', 'logfile', '') dirname = os.path.dirname(path) if dirname and not os.path.exists(dirname): os.makedirs(dirname) formatter = logging.Formatter( 'FW-Lite %(asctime)s %(levelname)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S') hdlr = logging.handlers.RotatingFileHandler(path, maxBytes=1048576, backupCount=5) hdlr.setFormatter(formatter) self.logger.addHandler(hdlr) self.region = set( x.upper() for x in self.userconf.dget('fgfwproxy', 'region', '').split('|') if x.strip()) self.profiles = len(self.userconf.dget('fgfwproxy', 'profile', '13')) self.xheaders = self.userconf.dgetbool('fgfwproxy', 'xheaders', False) if self.userconf.dget('fgfwproxy', 'parentproxy', ''): self.addparentproxy( 'direct', '%s 0' % self.userconf.dget('fgfwproxy', 'parentproxy', '')) self.addparentproxy('local', 'direct 100') else: self.addparentproxy('direct', 'direct 0') ParentProxy.set_via(self.parentlist.direct) for k, v in self.userconf.items('parents'): if '6Rc59g0jFlTppvel' in v: self.userconf.remove_option('parents', k) self.confsave() continue self.addparentproxy(k, v) if not self.rproxy and len([ k for k in self.parentlist.httpsparents() if k.httpspriority < 100 ]) == 0: self.logger.warning('No parent proxy available!') self.maxretry = self.userconf.dgetint('fgfwproxy', 'maxretry', 4) def addhost(host, ip): try: ipo = ip_address(ip) if isinstance(ipo, IPv4Address): self.HOSTS[host].append((2, ip)) else: self.HOSTS[host].append((10, ip)) except Exception: self.logging.warning('unsupported host: %s' % ip) for host, ip in self.userconf.items('hosts'): addhost(host, ip) if os.path.isfile('./fgfw-lite/hosts'): for line in open('./fgfw-lite/hosts'): line = line.strip() if line and not line.startswith('#'): try: ip, host = line.split() addhost(host, ip) except Exception as e: self.logger.warning('%s %s' % (e, line)) self.localdns = parse_hostport( self.userconf.dget( 'dns', 'localdns', '8.8.8.8:53' if self.rproxy else '223.5.5.5:53')) self.remotedns = self.localdns if self.rproxy else parse_hostport( self.userconf.dget('dns', 'remotedns', '208.67.222.222:5353')) self.REDIRECTOR = redirector(self) self.PARENT_PROXY = get_proxy(self) self.resolver = resolver.get_resolver( self.localdns, self.remotedns, ParentProxy('self', 'http://127.0.0.1:%d' % self.listen[1]), self.PARENT_PROXY.force)
def __init__(self): self.logger = logging.getLogger('config') self.logger.setLevel(logging.INFO) hdr = logging.StreamHandler() formatter = logging.Formatter( '%(asctime)s %(name)s:%(levelname)s %(message)s', datefmt='%H:%M:%S') hdr.setFormatter(formatter) self.logger.addHandler(hdr) self.version = SConfigParser() self.userconf = SConfigParser() self.reload() self.UPDATE_INTV = 6 self.timeout = self.userconf.dgetint('fgfwproxy', 'timeout', 3) ParentProxy.DEFAULT_TIMEOUT = self.timeout self.parentlist = ParentProxyList() self.HOSTS = defaultdict(list) self.GUI = '-GUI' in sys.argv self.rproxy = self.userconf.dgetbool('fgfwproxy', 'rproxy', False) listen = self.userconf.dget('fgfwproxy', 'listen', '8118') if listen.isdigit(): self.listen = ('127.0.0.1', int(listen)) else: self.listen = (listen.rsplit(':', 1)[0], int(listen.rsplit(':', 1)[1])) try: csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) csock.connect(('8.8.8.8', 53)) (addr, port) = csock.getsockname() csock.close() self.local_ip = addr except socket.error: self.local_ip = '127.0.0.1' ip = self.local_ip self.PAC = PAC.replace('__PROXY__', 'PROXY %s:%s' % (ip, self.listen[1])) if self.userconf.dget('fgfwproxy', 'pac', ''): if os.path.isfile(self.userconf.dget('fgfwproxy', 'pac', '')): self.PAC = open(self.userconf.dget('fgfwproxy', 'pac', '')).read() self.PAC = self.PAC.encode() if self.userconf.dget('FGFW_Lite', 'logfile', ''): path = self.userconf.dget('FGFW_Lite', 'logfile', '') dirname = os.path.dirname(path) if dirname and not os.path.exists(dirname): os.makedirs(dirname) formatter = logging.Formatter( 'FW-Lite %(asctime)s %(levelname)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S') hdlr = logging.handlers.RotatingFileHandler(path, maxBytes=1048576, backupCount=5) hdlr.setFormatter(formatter) self.logger.addHandler(hdlr) self.region = set( x.upper() for x in self.userconf.dget('fgfwproxy', 'region', '').split('|') if x.strip()) self.profile_num = len(self.userconf.dget('fgfwproxy', 'profile', '13')) self.xheaders = self.userconf.dgetbool('fgfwproxy', 'xheaders', False) if self.userconf.dget('fgfwproxy', 'parentproxy', ''): self.addparentproxy( 'direct', '%s 0' % self.userconf.dget('fgfwproxy', 'parentproxy', '')) self.addparentproxy('local', 'direct 100') else: self.addparentproxy('direct', 'direct 0') ParentProxy.set_via(self.parentlist.direct) for k, v in self.userconf.items('parents'): if '6Rc59g0jFlTppvel' in v: self.userconf.remove_option('parents', k) self.confsave() continue self.addparentproxy(k, v) if not self.rproxy and len([ k for k in self.parentlist.httpsparents() if k.httpspriority < 100 ]) == 0: self.logger.warning('No parent proxy available!') self.maxretry = self.userconf.dgetint('fgfwproxy', 'maxretry', 4) def addhost(host, ip): try: ipo = ip_address(ip) if isinstance(ipo, IPv4Address): self.HOSTS[host].append((2, ip)) else: self.HOSTS[host].append((10, ip)) except Exception: self.logger.warning('unsupported host: %s' % ip) sys.stderr.write(traceback.format_exc() + '\n') sys.stderr.flush() for host, ip in self.userconf.items('hosts'): addhost(host, ip) if os.path.isfile('./fgfw-lite/hosts'): for line in open('./fgfw-lite/hosts'): line = line.strip() if line and not line.startswith('#'): try: ip, host = line.split() addhost(host, ip) except Exception as e: self.logger.warning('%s %s' % (e, line)) localdns = self.userconf.dget('dns', 'localdns', '') # get local dns setting from system if not localdns: if sys.platform.startswith('win'): import subprocess localdns = subprocess.check_output( ['nslookup', '127.0.0.1']).splitlines()[1].split()[1].decode() elif sys.platform == 'linux2': lst = [] with open('/etc/resolv.conf') as f: for line in f: if line.startswith('nameserver'): lst.append(line.split()[1]) localdns = '|'.join(lst) else: localdns = '119.29.29.29' self.logger.info('localdns: ' + localdns) self.localdns = [ parse_hostport(dns, 53) for dns in localdns.split('|') ] remotedns = localdns if self.rproxy else self.userconf.dget( 'dns', 'remotedns', '8.8.8.8') self.logger.info('remotedns: ' + remotedns) self.remotedns = [ parse_hostport(dns, 53) for dns in remotedns.split('|') ] self.REDIRECTOR = redirector(self) self.GET_PROXY = get_proxy(self) bad_ip = set(self.userconf.dget('dns', 'bad_ip', '').split('|')) self.resolver = resolver.get_resolver( self.localdns, self.remotedns, proxy=ParentProxy('self', 'http://127.0.0.1:%d' % self.listen[1]), apfilter=[self.GET_PROXY.gfwlist, self.GET_PROXY.local], bad_ip=bad_ip)
def do_GET(self): if isinstance(self.path, bytes): self.path = self.path.decode('latin1') if self.path.lower().startswith('ftp://'): return self.do_FTP() if self.path == '/pac': _ip = ip_address(parse_hostport(self.headers.get('Host', ''))[0]) if _ip.is_loopback or str(_ip) in self.conf.local_ip: return self.write(msg=self.conf.PAC, ctype='application/x-ns-proxy-autoconfig') # transparent proxy if self.path.startswith('/'): if 'Host' not in self.headers: return self.send_error(403) self.path = 'http://%s%s' % (self.headers['Host'], self.path) if self.path.startswith('http://http://'): self.path = self.path[7:] parse = urlparse.urlparse(self.path) if 'Host' not in self.headers: self.headers['Host'] = parse.netloc self.requesthost = parse_hostport(self.headers['Host'], 80) self.shortpath = '%s://%s%s%s%s' % (parse.scheme, parse.netloc, parse.path.split(':')[0], '?' if parse.query else '', ':' if ':' in parse.path else '') # redirector noxff = False new_url = self.conf.PARENT_PROXY.redirect(self) if new_url: self.logger.debug('redirect %s, %s %s' % (new_url, self.command, self.shortpath or self.path)) if new_url.isdigit() and 400 <= int(new_url) < 600: return self.send_error(int(new_url)) elif new_url.lower() == 'noxff': noxff = True elif new_url.lower() == 'reset': self.close_connection = 1 return elif new_url.lower() == 'adblock': return self.write(msg=FAKEGIF, ctype='image/gif') elif all(u in self.conf.parentlist.dict.keys() for u in new_url.split()): self._proxylist = [self.conf.parentlist.get(u) for u in new_url.split()] random.shuffle(self._proxylist) else: return self.redirect(new_url) ip = self.conf.resolver.get_ip_address(self.requesthost[0]) if ip.is_loopback or self.ssclient: if ip_address(self.client_address[0]).is_loopback: if self.requesthost[1] in range(self.conf.listen[1], self.conf.listen[1] + self.conf.profiles): return self.api(parse) else: return self.send_error(403, 'Go f**k yourself!') if str(ip) == self.connection.getsockname()[0]: if self.requesthost[1] in range(self.conf.listen[1], self.conf.listen[1] + len(self.conf.userconf.dget('fgfwproxy', 'profile', '134'))): if self.conf.userconf.dgetbool('fgfwproxy', 'remoteapi', False): return self.api(parse) return self.send_error(403) if not self.ssclient and self.conf.xheaders: ipl = [client_ip.strip() for client_ip in self.headers.get('X-Forwarded-For', '').split(',') if client_ip.strip()] ipl.append(self.client_address[0]) self.headers['X-Forwarded-For'] = ', '.join(ipl) if noxff: del self.headers['X-Forwarded-For'] self._do_GET()