def _get_forwarded_ip(headers): header = headers.get('x-forwarded-for') if header: try: x, y = header.split(',') except: return header if is_valid_ip(x) and x not in local_IPs: return x return y header = headers.get('client-ip') if header: return header header = headers.get('via') if header: x = http_via_filter.search(header) try: return x.group(1) except: pass header = headers.get('from') #if header: # return header #return None return header
def add_data(self, infohash, event, ip, paramslist): peers = self.downloads.setdefault(infohash, {}) ts = self.times.setdefault(infohash, {}) self.completed.setdefault(infohash, 0) self.seedcount.setdefault(infohash, 0) def params(key, default=None, l=paramslist): if key in l: return l[key][0] return default myid = params('peer_id', '') if len(myid) != 20: raise ValueError('id not of length 20') if event not in ('started', 'completed', 'stopped', 'snooped', None): raise ValueError('invalid event') port = params('cryptoport') if port is None: port = params('port', '') port = long(port) if port < 0 or port > 65535: raise ValueError('invalid port') left = long(params('left', '')) if left < 0: raise ValueError('invalid amount left') #uploaded = long(params('uploaded','')) #downloaded = long(params('downloaded','')) if params('supportcrypto'): supportcrypto = 1 try: s = int(params['requirecrypto']) chr(s) except: s = 0 requirecrypto = s else: supportcrypto = 0 requirecrypto = 0 peer = peers.get(myid) islocal = ip in local_IPs mykey = params('key') if peer: auth = peer.get('key', -1) == mykey or peer.get('ip') == ip gip = params('ip') if is_valid_ip(gip) and (islocal or not self.only_local_override_ip): ip1 = gip else: ip1 = ip if params('numwant') is not None: rsize = min(int(params('numwant')), self.response_size) else: rsize = self.response_size if event == 'stopped': if peer: if auth: self.delete_peer(infohash, myid) elif not peer: ts[myid] = clock() peer = {'ip': ip, 'port': port, 'left': left, 'supportcrypto': supportcrypto, 'requirecrypto': requirecrypto} if mykey: peer['key'] = mykey if gip: peer['given ip'] = gip if port: if not self.natcheck or islocal: peer['nat'] = 0 self.natcheckOK(infohash, myid, ip1, port, peer) else: NatCheck(self.connectback_result, infohash, myid, ip1, port, self.rawserver, encrypted=requirecrypto) else: peer['nat'] = 2 ** 30 if event == 'completed': self.completed[infohash] += 1 if not left: self.seedcount[infohash] += 1 peers[myid] = peer else: if not auth: return rsize # return w/o changing stats ts[myid] = clock() if not left and peer['left']: self.completed[infohash] += 1 self.seedcount[infohash] += 1 if not peer.get('nat', -1): for bc in self.becache[infohash]: bc[1][myid] = bc[0][myid] del bc[0][myid] elif left and not peer['left']: self.completed[infohash] -= 1 self.seedcount[infohash] -= 1 if not peer.get('nat', -1): for bc in self.becache[infohash]: bc[0][myid] = bc[1][myid] del bc[1][myid] peer['left'] = left if port: recheck = False if ip != peer['ip']: peer['ip'] = ip recheck = True if gip != peer.get('given ip'): if gip: peer['given ip'] = gip elif 'given ip' in peer: del peer['given ip'] recheck = True natted = peer.get('nat', -1) if recheck: if natted == 0: l = self.becache[infohash] y = not peer['left'] for x in l: del x[y][myid] if natted >= 0: del peer['nat'] # restart NAT testing if natted and natted < self.natcheck: recheck = True if recheck: if not self.natcheck or islocal: peer['nat'] = 0 self.natcheckOK(infohash, myid, ip1, port, peer) else: NatCheck(self.connectback_result, infohash, myid, ip1, port, self.rawserver, encrypted=requirecrypto) return rsize
def __init__(self, config, rawserver): self.config = config self.response_size = config['response_size'] self.dfile = config['dfile'] self.natcheck = config['nat_check'] favicon = config['favicon'] self.parse_dir_interval = config['parse_dir_interval'] self.favicon = None if favicon: try: with open(favicon, 'r') as h: self.favicon = h.read() except: print "**warning** specified favicon file -- %s -- does not " \ "exist." % favicon self.rawserver = rawserver self.cached = {} # format: infohash: [[time1, l1, s1], ...] self.cached_t = {} # format: infohash: [time, cache] self.times = {} self.state = {} self.seedcount = {} self.allowed_IPs = None self.banned_IPs = None if config['allowed_ips'] or config['banned_ips']: self.allowed_ip_mtime = 0 self.banned_ip_mtime = 0 self.read_ip_lists() self.only_local_override_ip = config['only_local_override_ip'] if self.only_local_override_ip == 2: self.only_local_override_ip = not config['nat_check'] if CHECK_PEER_ID_ENCRYPTED and not CRYPTO_OK: print '**warning** crypto library not installed, cannot ' \ 'completely verify encrypted peers' if os.path.exists(self.dfile): try: with open(self.dfile, 'rb') as h: ds = h.read() tempstate = bdecode(ds) if 'peers' not in tempstate: tempstate = {'peers': tempstate} statefiletemplate(tempstate) self.state = tempstate except: print '**warning** statefile ' + self.dfile + \ ' corrupt; resetting' self.downloads = self.state.setdefault('peers', {}) self.completed = self.state.setdefault('completed', {}) self.becache = {} ''' format: infohash: [[l0, s0], [l1, s1], ...] l0,s0 = compact, not requirecrypto=1 l1,s1 = compact, only supportcrypto=1 l2,s2 = [compact, crypto_flag], all peers if --compact_reqd 0: l3,s3 = [ip,port,id] l4,l4 = [ip,port] nopeerid ''' if config['compact_reqd']: x = 3 else: x = 5 self.cache_default = [({}, {}) for i in xrange(x)] for infohash, ds in self.downloads.iteritems(): self.seedcount[infohash] = 0 for x, y in ds.iteritems(): ip = y['ip'] if self.allowed_IPs and ip not in self.allowed_IPs \ or self.banned_IPs and ip in self.banned_IPs: del ds[x] continue if not y['left']: self.seedcount[infohash] += 1 if y.get('nat', -1): continue gip = y.get('given_ip') if is_valid_ip(gip) and (not self.only_local_override_ip or ip in local_IPs): ip = gip self.natcheckOK(infohash, x, ip, y['port'], y) for x in self.downloads: self.times[x] = {} for y in self.downloads[x]: self.times[x][y] = 0 self.trackerid = createPeerID('-T-') random.seed(self.trackerid) self.reannounce_interval = config['reannounce_interval'] self.save_dfile_interval = config['save_dfile_interval'] self.show_names = config['show_names'] rawserver.add_task(self.save_state, self.save_dfile_interval) self.prevtime = clock() self.timeout_downloaders_interval = config[ 'timeout_downloaders_interval'] rawserver.add_task(self.expire_downloaders, self.timeout_downloaders_interval) self.logfile = None self.log = None if (config['logfile']) and (config['logfile'] != '-'): try: self.logfile = config['logfile'] self.log = open(self.logfile, 'a') sys.stdout = self.log print "# Log Started: ", isotime() except: print "**warning** could not redirect stdout to log file: " + \ sys.exc_info()[0] if config['hupmonitor']: def huphandler(signum, frame, self=self): try: self.log.close() self.log = open(self.logfile, 'a') sys.stdout = self.log print "# Log reopened: ", isotime() except: print "**warning** could not reopen logfile" signal.signal(signal.SIGHUP, huphandler) self.allow_get = config['allow_get'] self.t2tlist = T2TList(config['multitracker_enabled'], self.trackerid, config['multitracker_reannounce_interval'], config['multitracker_maxpeers'], config['http_timeout'], self.rawserver) if config['allowed_list']: if config['allowed_dir']: print '**warning** allowed_dir and allowed_list options ' \ 'cannot be used together' print '**warning** disregarding allowed_dir' config['allowed_dir'] = '' self.allowed = self.state.setdefault('allowed_list', {}) self.allowed_list_mtime = 0 self.parse_allowed() self.remove_from_state('allowed', 'allowed_dir_files') if config['multitracker_allowed'] == 'autodetect': config['multitracker_allowed'] = 'none' config['allowed_controls'] = 0 elif config['allowed_dir']: self.allowed = self.state.setdefault('allowed', {}) self.allowed_dir_files = self.state.setdefault( 'allowed_dir_files', {}) self.allowed_dir_blocked = set() self.parse_allowed() self.remove_from_state('allowed_list') else: self.allowed = None self.remove_from_state('allowed', 'allowed_dir_files', 'allowed_list') if config['multitracker_allowed'] == 'autodetect': config['multitracker_allowed'] = 'none' config['allowed_controls'] = 0 self.uq_broken = unquote('+') != ' ' self.keep_dead = config['keep_dead'] self.Filter = Filter(rawserver.add_task) aggregator = config['aggregator'] if aggregator == '0': self.is_aggregator = False self.aggregator_key = None else: self.is_aggregator = True if aggregator == '1': self.aggregator_key = None else: self.aggregator_key = aggregator self.natcheck = False send = config['aggregate_forward'] if not send: self.aggregate_forward = None else: sends = send.split(',') self.aggregate_forward = sends[0] self.aggregate_password = sends[1] if len(sends) > 1 else None self.dedicated_seed_id = config['dedicated_seed_id'] self.is_seeded = {} self.cachetime = 0 self.cachetimeupdate()
def get_forwarded_ip(headers): x = _get_forwarded_ip(headers) if not is_valid_ip(x) or x in local_IPs: return None return x