def new_server(self, port, passwd, cfg): protocol = cfg.get('protocol', ServerPool.get_instance().config.get('protocol', 'origin')) method = cfg.get('method', ServerPool.get_instance().config.get('method', 'None')) obfs = cfg.get('obfs', ServerPool.get_instance().config.get('obfs', 'plain')) logging.info('db start server at port [%s] pass [%s] protocol [%s] method [%s] obfs [%s]' % (port, passwd, protocol, method, obfs)) ServerPool.get_instance().new_server(port, cfg) self.force_update_transfer.add(port)
def thread_db(obj): import socket import time global db_instance timeout = 60 socket.setdefaulttimeout(timeout) last_rows = [] db_instance = obj() ServerPool.get_instance() shell.log_shadowsocks_version() import resource logging.info('current process RLIMIT_NOFILE resource: soft %d hard %d' % resource.getrlimit(resource.RLIMIT_NOFILE)) try: while True: load_config() db_instance.load_cfg() try: db_instance.push_db_all_user() rows = db_instance.pull_db_all_user() if rows: db_instance.pull_ok = True db_instance.del_server_out_of_bound_safe(last_rows, rows) last_rows = rows except Exception as e: trace = traceback.format_exc() logging.error(trace) #logging.warn('db thread except:%s' % e) if db_instance.event.wait(get_config().UPDATE_TIME) or not ServerPool.get_instance().thread.is_alive(): break except KeyboardInterrupt as e: pass db_instance.del_servers() ServerPool.get_instance().stop() db_instance = None
def del_server_out_of_bound_safe(rows): # 停止超流量的服务 # 启动没超流量的服务 for row in rows: if ServerPool.get_instance().server_is_run(row[0]): if row[1] + row[2] >= row[3]: logging.info("db stop server at port [%s]" % (row[0])) ServerPool.get_instance().del_server(row[0]) else: if row[5] == 1 and row[6] == 1 and row[1] + row[2] < row[3]: logging.info("db start server at port [%s] pass [%s]" % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4])
def thread_db(obj): import socket import time global db_instance timeout = 60 socket.setdefaulttimeout(timeout) last_rows = [] db_instance = obj() ServerPool.get_instance() shell.log_shadowsocks_version() try: import resource logging.info('current process RLIMIT_NOFILE resource: soft %d hard %d' % resource.getrlimit(resource.RLIMIT_NOFILE)) except: pass try: while True: load_config() db_instance.load_cfg() try: db_instance.push_db_all_user() rows = db_instance.pull_db_all_user() if rows: db_instance.pull_ok = True config = shell.get_config(False) for port in config['additional_ports']: val = config['additional_ports'][port] val['port'] = int(port) val['enable'] = 1 val['transfer_enable'] = 1024 ** 7 val['u'] = 0 val['d'] = 0 if "password" in val: val["passwd"] = val["password"] rows.append(val) db_instance.del_server_out_of_bound_safe(last_rows, rows) last_rows = rows except Exception as e: trace = traceback.format_exc() logging.error(trace) #logging.warn('db thread except:%s' % e) if db_instance.event.wait(get_config().UPDATE_TIME) or not ServerPool.get_instance().thread.is_alive(): break except KeyboardInterrupt as e: pass db_instance.del_servers() ServerPool.get_instance().stop() db_instance = None
def del_servers(): for port in [v for v in ServerPool.get_instance().tcp_servers_pool.keys()]: if ServerPool.get_instance().server_is_run(port) > 0: ServerPool.get_instance().cb_del_server(port) for port in [v for v in ServerPool.get_instance().tcp_ipv6_servers_pool.keys()]: if ServerPool.get_instance().server_is_run(port) > 0: ServerPool.get_instance().cb_del_server(port)
def push_db_all_user(self): if self.pull_ok is False: return current_transfer=ServerPool.get_instance().get_servers_transfer() dt_transfer={} for id in self.force_update_transfer: if id in self.last_update_transfer: if self.force_update_transfer[id][0]+self.force_update_transfer[id][1]>self.last_update_transfer[id][0]+self.last_update_transfer[id][1]: dt_transfer[id]=[self.force_update_transfer[id][0]-self.last_update_transfer[id][0], self.force_update_transfer[id][1]-self.last_update_transfer[id][1]] del self.last_update_transfer[id] for id in current_transfer: if id in self.force_update_transfer: continue if id in self.last_update_transfer: if current_transfer[id][0]+current_transfer[id][1]-self.last_update_transfer[id][0]-self.last_update_transfer[id][1]<=0: continue dt_transfer[id]=[current_transfer[id][0]-self.last_update_transfer[id][0],current_transfer[id][1]-self.last_update_transfer[id][1]] else: if current_transfer[id][0]+current_transfer[id][1]<=0: continue dt_transfer[id]=[current_transfer[id][0],current_transfer[id][1]] self.update_all_user(dt_transfer) for id in dt_transfer: if id not in self.force_update_transfer: last=self.last_update_transfer.get(id,[0,0]) self.last_update_transfer[id]=[last[0]+dt_transfer[id][0],last[1]+dt_transfer[id][1]] self.force_update_transfer={}
def push_db_all_user(self): if self.pull_ok is False: return #更新用户流量到数据库 last_transfer = self.last_update_transfer curr_transfer = ServerPool.get_instance().get_servers_transfer() #上次和本次的增量 dt_transfer = {} for id in self.force_update_transfer: #此表中的用户统计上次未计入的流量 if id in self.last_get_transfer and id in last_transfer: dt_transfer[id] = [ self.last_get_transfer[id][0] - last_transfer[id][0], self.last_get_transfer[id][1] - last_transfer[id][1] ] for id in curr_transfer.keys(): if id in self.force_update_transfer or id in self.mu_ports: continue #算出与上次记录的流量差值,保存于dt_transfer表 if id in last_transfer: if curr_transfer[id][0] + curr_transfer[id][1] - last_transfer[ id][0] - last_transfer[id][1] <= 0: continue dt_transfer[id] = [ curr_transfer[id][0] - last_transfer[id][0], curr_transfer[id][1] - last_transfer[id][1] ] else: if curr_transfer[id][0] + curr_transfer[id][1] <= 0: continue dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] #有流量的,先记录在线状态 if id in self.last_get_transfer: if curr_transfer[id][0] + curr_transfer[id][ 1] > self.last_get_transfer[id][ 0] + self.last_get_transfer[id][1]: self.onlineuser_cache[ id] = curr_transfer[id][0] + curr_transfer[id][1] else: self.onlineuser_cache[ id] = curr_transfer[id][0] + curr_transfer[id][1] self.onlineuser_cache.sweep() update_transfer = self.update_all_user(dt_transfer) #返回有更新的表 for id in update_transfer.keys(): #其增量加在此表 if id not in self.force_update_transfer: #但排除在force_update_transfer内的 last = self.last_update_transfer.get(id, [0, 0]) self.last_update_transfer[id] = [ last[0] + update_transfer[id][0], last[1] + update_transfer[id][1] ] self.last_get_transfer = curr_transfer for id in self.force_update_transfer: if id in self.last_update_transfer: del self.last_update_transfer[id] if id in self.last_get_transfer: del self.last_get_transfer[id] self.force_update_transfer = set()
def push_db_all_user(self): # 更新用户流量到数据库 last_transfer = self.last_update_transfer curr_transfer = ServerPool.get_instance().get_servers_transfer() # 上次和本次的增量 dt_transfer = {} for id in curr_transfer.keys(): if id in last_transfer: if curr_transfer[id][0] + curr_transfer[id][1] - \ last_transfer[id][0] - last_transfer[id][1] <= 0: continue if last_transfer[id][0] <= curr_transfer[id][0] and \ last_transfer[id][1] <= curr_transfer[id][1]: dt_transfer[id] = [ curr_transfer[id][0] - last_transfer[id][0], curr_transfer[id][1] - last_transfer[id][1] ] else: dt_transfer[id] = [ curr_transfer[id][0], curr_transfer[id][1] ] else: if curr_transfer[id][0] + curr_transfer[id][1] <= 0: continue dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] for id in dt_transfer.keys(): last = last_transfer.get(id, [0, 0]) last_transfer[id] = [ last[0] + dt_transfer[id][0], last[1] + dt_transfer[id][1] ] self.last_update_transfer = last_transfer.copy() self.update_all_user(dt_transfer)
def push_db_all_user(self): #更新用户流量到数据库 last_transfer = self.last_get_transfer curr_transfer = ServerPool.get_instance().get_servers_transfer() #上次和本次的增量 dt_transfer = {} for id in curr_transfer.keys(): if id in last_transfer: if last_transfer[id][0] == curr_transfer[id][0] and last_transfer[id][1] == curr_transfer[id][1]: continue elif curr_transfer[id][0] == 0 and curr_transfer[id][1] == 0: continue elif last_transfer[id][0] <= curr_transfer[id][0] and \ last_transfer[id][1] <= curr_transfer[id][1]: dt_transfer[id] = [curr_transfer[id][0] - last_transfer[id][0], curr_transfer[id][1] - last_transfer[id][1]] else: dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] else: if curr_transfer[id][0] == 0 and curr_transfer[id][1] == 0: continue dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] self.last_get_transfer = curr_transfer for id in dt_transfer.keys(): ins = SSInstance.objects.get(port=id) # print u ins.u += dt_transfer[id][0] ins.d += dt_transfer[id][1] # print u ins.save()
def thread_db(obj): import socket import time import webapi_utils global db_instance global webapi timeout = 60 socket.setdefaulttimeout(timeout) last_rows = [] db_instance = obj() webapi = webapi_utils.WebApi() shell.log_shadowsocks_version() try: import resource logging.info( 'current process RLIMIT_NOFILE resource: soft %d hard %d' % resource.getrlimit(resource.RLIMIT_NOFILE)) except: pass try: while True: load_config() try: ping = webapi.getApi('func/ping') if ping is None: logging.error( 'something wrong with your http api, please check your config and website status and try again later.' ) else: db_instance.push_db_all_user() rows = db_instance.pull_db_all_user() db_instance.del_server_out_of_bound_safe( last_rows, rows) last_rows = rows except Exception as e: trace = traceback.format_exc() logging.error(trace) # logging.warn('db thread except:%s' % e) if db_instance.event.wait( 60) or not db_instance.is_all_thread_alive(): break except KeyboardInterrupt as e: pass db_instance.del_servers() ServerPool.get_instance().stop() db_instance = None
def push_db_all_user(self): #更新用户流量到数据库 last_transfer = self.last_get_transfer curr_transfer = ServerPool.get_instance().get_servers_transfer() #上次和本次的增量 dt_transfer = {} for id in curr_transfer.keys(): if id in last_transfer: if last_transfer[id][0] == curr_transfer[id][ 0] and last_transfer[id][1] == curr_transfer[id][1]: continue elif curr_transfer[id][0] == 0 and curr_transfer[id][1] == 0: continue elif last_transfer[id][0] <= curr_transfer[id][0] and \ last_transfer[id][1] <= curr_transfer[id][1]: dt_transfer[id] = [ curr_transfer[id][0] - last_transfer[id][0], curr_transfer[id][1] - last_transfer[id][1] ] else: dt_transfer[id] = [ curr_transfer[id][0], curr_transfer[id][1] ] else: if curr_transfer[id][0] == 0 and curr_transfer[id][1] == 0: continue dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] self.last_get_transfer = curr_transfer query_head = 'UPDATE user' query_sub_when = '' query_sub_when2 = '' query_sub_in = None last_time = time.time() for id in dt_transfer.keys(): query_sub_when += ' WHEN %s THEN u+%s' % (id, dt_transfer[id][0]) query_sub_when2 += ' WHEN %s THEN d+%s' % (id, dt_transfer[id][1]) if query_sub_in is not None: query_sub_in += ',%s' % id else: query_sub_in = '%s' % id if query_sub_when == '': return query_sql = query_head + ' SET u = CASE port' + query_sub_when + \ ' END, d = CASE port' + query_sub_when2 + \ ' END, t = ' + str(int(last_time)) + \ ' WHERE port IN (%s)' % query_sub_in #print query_sql conn = cymysql.connect(host=Config.MYSQL_HOST, port=Config.MYSQL_PORT, user=Config.MYSQL_USER, passwd=Config.MYSQL_PASS, db=Config.MYSQL_DB, charset='utf8') cur = conn.cursor() cur.execute(query_sql) cur.close() conn.commit() conn.close()
def thread_db(obj): import socket import time global db_instance timeout = 60 socket.setdefaulttimeout(timeout) last_rows = [] db_instance = obj() ServerPool.get_instance() shell.log_shadowsocks_version() try: import resource logging.info( 'current process RLIMIT_NOFILE resource: soft %d hard %d' % resource.getrlimit(resource.RLIMIT_NOFILE)) except: pass try: while True: load_config() try: db_instance.push_db_all_user() rows = db_instance.pull_db_all_user() if rows == -1: raise Exception elif rows == -2: rows = last_rows elif rows: db_instance.pull_ok = True db_instance.del_server_out_of_bound_safe(last_rows, rows) last_rows = rows except Exception as e: trace = traceback.format_exc() logging.error(trace) #logging.warn('db thread except:%s' % e) if db_instance.event.wait( get_config().API_UPDATE_TIME ) or not ServerPool.get_instance().thread.is_alive(): break except KeyboardInterrupt as e: pass db_instance.del_servers() ServerPool.get_instance().stop() db_instance = None
def get_free_port(start_port=10000): all_port = os.popen('netstat -na').read() for i in range(int(start_port), 60000): if str( i ) not in all_port and i % 500 != 0 and i not in ServerPool.get_instance( ).tcp_servers_pool: return i
def new_server(self, port, passwd, cfg): self.pull_db_all_user() protocol = cfg.get( 'protocol', ServerPool.get_instance().config.get('protocol', 'origin')) method = cfg.get( 'method', ServerPool.get_instance().config.get('method', 'None')) obfs = cfg.get('obfs', ServerPool.get_instance().config.get('obfs', 'plain')) if self.mu_only == 1: new_port = port + self.port_offset else: new_port = port logging.info( 'db start server at port [%s] pass [%s] protocol [%s] method [%s] obfs [%s]' % (new_port, passwd, protocol, method, obfs)) ServerPool.get_instance().new_server(new_port, cfg)
def del_servers(): for port in [ v for v in ServerPool.get_instance().tcp_servers_pool.keys() ]: if ServerPool.get_instance().server_is_run(port) > 0: ServerPool.get_instance().cb_del_server(port) for port in [ v for v in ServerPool.get_instance().tcp_ipv6_servers_pool.keys() ]: if ServerPool.get_instance().server_is_run(port) > 0: ServerPool.get_instance().cb_del_server(port)
def get_diff_transfer(self): diff_transfer = {} curr_transfer = ServerPool.get_instance().get_servers_transfer() for port in curr_transfer: diff = curr_transfer[port] - self._last_transfer[port] if diff <= 1024: continue diff_transfer[port] = diff self._last_transfer = curr_transfer return diff_transfer
def del_servers(): global db_instance for port in [v for v in ServerPool.get_instance().tcp_servers_pool.keys()]: if ServerPool.get_instance().server_is_run(port) > 0: ServerPool.get_instance().cb_del_server(port) if port in db_instance.last_update_transfer: del db_instance.last_update_transfer[port] for port in [v for v in ServerPool.get_instance().tcp_ipv6_servers_pool.keys()]: if ServerPool.get_instance().server_is_run(port) > 0: ServerPool.get_instance().cb_del_server(port) if port in db_instance.last_update_transfer: del db_instance.last_update_transfer[port]
def push_db_all_user(self): #更新用户流量到数据库 last_transfer = self.last_get_transfer curr_transfer = ServerPool.get_instance().get_servers_transfer() #上次和本次的增量 dt_transfer = {} for id in curr_transfer.keys(): if id in last_transfer: if last_transfer[id][0] == curr_transfer[id][0] and last_transfer[id][1] == curr_transfer[id][1]: continue elif curr_transfer[id][0] == 0 and curr_transfer[id][1] == 0: continue elif last_transfer[id][0] <= curr_transfer[id][0] and \ last_transfer[id][1] <= curr_transfer[id][1]: dt_transfer[id] = [curr_transfer[id][0] - last_transfer[id][0], curr_transfer[id][1] - last_transfer[id][1]] else: dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] else: if curr_transfer[id][0] == 0 and curr_transfer[id][1] == 0: continue dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] self.last_get_transfer = curr_transfer query_head = 'UPDATE users' query_sub_when = '' query_sub_when2 = '' query_sub_when3 = '' query_sub_in = None last_time = time.time() for id in dt_transfer.keys(): totalU = dt_transfer[id][0] totalD = dt_transfer[id][1] query_sub_when += ' WHEN %s THEN u+%s' % (id, totalU) query_sub_when2 += ' WHEN %s THEN d+%s' % (id, totalD) query_sub_when3 += ' WHEN %s THEN total_transfer+%s' % (id, totalD+totalU) if query_sub_in is not None: query_sub_in += ',%s' % id else: query_sub_in = '%s' % id if query_sub_when == '': return query_sql = query_head + ' SET u = CASE port' + query_sub_when + \ ' END, d = CASE port' + query_sub_when2 + \ ' END, total_transfer = CASE port' + query_sub_when3 + \ ' END, t = ' + str(int(last_time)) + \ ' WHERE port IN (%s)' % query_sub_in #print query_sql conn = cymysql.connect(host=Config.MYSQL_HOST, port=Config.MYSQL_PORT, user=Config.MYSQL_USER, passwd=Config.MYSQL_PASS, db=Config.MYSQL_DB, charset='utf8') cur = conn.cursor() cur.execute(query_sql) cur.close() conn.commit() conn.close()
def thread_db(obj): import socket import time global db_instance timeout = 60 socket.setdefaulttimeout(timeout) last_rows = [] db_instance = obj() shell.log_shadowsocks_version() try: import resource logging.info( 'current process RLIMIT_NOFILE resource: soft %d hard %d' % resource.getrlimit(resource.RLIMIT_NOFILE)) except: pass try: while True: load_config() try: db_instance.push_db_all_user() rows = db_instance.pull_db_all_user() db_instance.del_server_out_of_bound_safe(last_rows, rows) db_instance.detect_text_ischanged = False db_instance.detect_hex_ischanged = False last_rows = rows db_instance.closeMysqlConn() except Exception as e: trace = traceback.format_exc() logging.error(trace) # logging.warn('db thread except:%s' % e) if db_instance.event.wait( 60) or not db_instance.is_all_thread_alive(): break if db_instance.has_stopped: break except KeyboardInterrupt as e: pass db_instance.del_servers() ServerPool.get_instance().stop() db_instance = None
def new_server(self, port, passwd, cfg): protocol = cfg.get( 'protocol', ServerPool.get_instance().config.get( 'protocol', 'origin')) method = cfg.get( 'method', ServerPool.get_instance().config.get( 'method', 'None')) obfs = cfg.get( 'obfs', ServerPool.get_instance().config.get( 'obfs', 'plain')) logging.info( 'db start server at port [%s] pass [%s] protocol [%s] method [%s] obfs [%s]' % (port, passwd, protocol, method, obfs)) ServerPool.get_instance().new_server(port, cfg)
def push_db_all_user(self): #更新用户流量到数据库 last_transfer = self.last_get_transfer curr_transfer = ServerPool.get_instance().get_servers_transfer() #上次和本次的增量 dt_transfer = {} for id in curr_transfer.keys(): if id in last_transfer: if last_transfer[id][0] == curr_transfer[id][0] and last_transfer[id][1] == curr_transfer[id][1]: continue elif curr_transfer[id][0] == 0 and curr_transfer[id][1] == 0: continue elif last_transfer[id][0] <= curr_transfer[id][0] and \ last_transfer[id][1] <= curr_transfer[id][1]: dt_transfer[id] = [int((curr_transfer[id][0] - last_transfer[id][0]) * Config.TRANSFER_MUL), int((curr_transfer[id][1] - last_transfer[id][1]) * Config.TRANSFER_MUL)] else: dt_transfer[id] = [int(curr_transfer[id][0] * Config.TRANSFER_MUL), int(curr_transfer[id][1] * Config.TRANSFER_MUL)] else: if curr_transfer[id][0] == 0 and curr_transfer[id][1] == 0: continue dt_transfer[id] = [int(curr_transfer[id][0] * Config.TRANSFER_MUL), int(curr_transfer[id][1] * Config.TRANSFER_MUL)] query_head = 'UPDATE member' query_sub_when = '' query_sub_when2 = '' query_sub_in = None last_time = time.time() for id in dt_transfer.keys(): if dt_transfer[id][0] == 0 and dt_transfer[id][1] == 0: continue query_sub_when += ' WHEN %s THEN flow_up+%s' % (id, dt_transfer[id][0]) query_sub_when2 += ' WHEN %s THEN flow_down+%s' % (id, dt_transfer[id][1]) if query_sub_in is not None: query_sub_in += ',%s' % id else: query_sub_in = '%s' % id if query_sub_when == '': return query_sql = query_head + ' SET flow_up = CASE port' + query_sub_when + \ ' END, flow_down = CASE port' + query_sub_when2 + \ ' END, lastConnTime = ' + str(int(last_time)) + \ ' WHERE port IN (%s)' % query_sub_in #print query_sql conn = cymysql.connect(host=Config.MYSQL_HOST, port=Config.MYSQL_PORT, user=Config.MYSQL_USER, passwd=Config.MYSQL_PASS, db=Config.MYSQL_DB, charset='utf8') cur = conn.cursor() cur.execute(query_sql) cur.close() conn.commit() conn.close() self.last_get_transfer = curr_transfer
def del_server_out_of_bound_safe(rows): #停止超流量的服务 #启动没超流量的服务 #修改下面的逻辑要小心包含跨线程访问 for row in rows: if ServerPool.get_instance().server_is_run(row[0]) is True: if row[5] == 0 or row[6] == 0: #stop disable or switch off user logging.info('db stop server at port [%s] reason: disable' % (row[0])) ServerPool.get_instance().del_server(row[0]) elif row[1] + row[2] >= row[3]: #stop out bandwidth user logging.info('db stop server at port [%s] reason: out bandwidth' % (row[0])) ServerPool.get_instance().del_server(row[0]) if ServerPool.get_instance().tcp_servers_pool[row[0]]._config['password'] != row[4]: #password changed logging.info('db stop server at port [%s] reason: password changed' % (row[0])) ServerPool.get_instance().del_server(row[0]) else: if row[5] == 1 and row[6] == 1 and row[1] + row[2] < row[3]: logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4])
def update_all_user(self, dt_transfer): node_id = get_config().NODE_ID update_transfer = {} # 用户流量上报 data = [] for id in dt_transfer.keys(): if dt_transfer[id][0] == 0 and dt_transfer[id][1] == 0: continue data.append({ 'u': dt_transfer[id][0], 'd': dt_transfer[id][1], 'user_id': self.port_uid_table[id] }) update_transfer[id] = dt_transfer[id] if len(data) > 0: api = EhcoApi() api.postApi('/traffic/upload', {'node_id': node_id, 'data': data}) api.close() # 节点在线ip上报 node_online_ip = ServerPool.get_instance().get_servers_ip_list() ip_data = {} for k, v in node_online_ip.items(): ip_data[self.port_uid_table[k]] = v if len(ip_data) > 0: api = EhcoApi() api.postApi('/nodes/aliveip', { 'node_id': node_id, 'data': ip_data }) api.close() # # 节点状态上报 # self.api.postApi( # '/nodes/load', # {'node_id': node_id, # 'uptime': str(self.uptime()), # 'load': str(self.load())}) # 节点人数上报 api = EhcoApi() alive_user_count = len(self.onlineuser_cache) api.postApi( '/nodes/online', { 'node_id': node_id, 'online_user': alive_user_count, 'log_time': round(time.time()) }) api.close() return update_transfer
def push_all_port_and_connect(self): config = shell.get_config(False) keys = ['node_id', 'port', 'type', 'ip'] tcp_poll = None udp_poll = None if 'server_ipv6' in config: tcp_poll = ServerPool.get_instance().tcp_ipv6_servers_pool udp_poll = ServerPool.get_instance().udp_ipv6_servers_pool else: tcp_poll = ServerPool.get_instance().tcp_servers_pool udp_poll = ServerPool.get_instance().udp_servers_pool # 结果集 result = [] for (k, v) in tcp_poll.items(): if len(v['one_minute_ips']) > 0: result.append({ 'node': self.cfg['node_id'], 'port': k, 'type': 'tcp', 'ip': ','.join([from_map_ipv6_get_ipv4(x) for x in v['one_minute_ips']]), 'created_at': time.time() }) for (k, v) in udp_poll.items(): if len(v['one_minute_ips']) > 0: result.append({ 'node': self.cfg['node_id'], 'port': k, 'type': 'udp', 'ip': ','.join([from_map_ipv6_get_ipv4(x) for x in v['one_minute_ips']]), 'created_at': time.time() }) # 如果结果集不为空则更新数据库 if len(result) > 0: with database.atomic(): SsNodeIp.insert_many(result).execute() logging.info("push all user one minute connections finished")
def thread_db(): import socket import time timeout = 60 socket.setdefaulttimeout(timeout) last_rows = [] try: while True: reload(Config) try: DbTransfer.get_instance().push_db_all_user() rows = DbTransfer.get_instance().pull_db_all_user() DbTransfer.del_server_out_of_bound_safe(last_rows, rows) last_rows = rows except Exception as e: trace = traceback.format_exc() logging.error(trace) #logging.warn('db thread except:%s' % e) if DbTransfer.get_instance().event.wait(Config.MYSQL_UPDATE_TIME) or not ServerPool.get_instance().thread.is_alive(): break except KeyboardInterrupt as e: pass DbTransfer.del_servers() ServerPool.get_instance().stop()
def update_traffic(self): data = [] servers_traffic = ServerPool.get_instance().get_servers_traffic() for port in servers_traffic: userId = self._users[port].get('userId', None) if userId is None: continue diff = servers_traffic[port] - self._last_traffic[port] data.append({ 'userId': userId, 'flowUp': 0, 'flowDown': diff, }) self._last_traffic = servers_traffic self.upload_traffic(data)
def stop_or_start_server(self, user): is_run = ServerPool.get_instance().server_is_run(user['port']) if is_run and user['isDeleted']: logging.info('stop server at port [%s] reason: deleted' % (user['port'])) ServerPool.get_instance().del_server(user['port']) elif is_run and user['isLocked']: logging.info('stop server at port [%s] reason: disable' % (user['port'])) ServerPool.get_instance().del_server(user['port']) elif is_run and user['password'] != user['oldPassword']: logging.info('stop server at port [%s] reason: password changed' % (user['port'])) ServerPool.get_instance().del_server(user['port']) elif not is_run and not user['isDeleted'] and not user['isLocked']: logging.info('start server at port [%s] pass [%s]' % (user['port'], user['password'])) ServerPool.get_instance().add_server({ 'server_port': user['port'], 'password': user['password'] })
def push_db_all_user(self): if self.pull_ok is False: return #更新用户流量到数据库 last_transfer = self.last_update_transfer curr_transfer = ServerPool.get_instance().get_servers_transfer() #上次和本次的增量 dt_transfer = {} for id in self.force_update_transfer: #此表中的用户统计上次未计入的流量 if id in self.last_get_transfer and id in last_transfer: dt_transfer[id] = [self.last_get_transfer[id][0] - last_transfer[id][0], self.last_get_transfer[id][1] - last_transfer[id][1]] for id in curr_transfer.keys(): if id in self.force_update_transfer: continue #算出与上次记录的流量差值,保存于dt_transfer表 if id in last_transfer: if curr_transfer[id][0] + curr_transfer[id][1] - last_transfer[id][0] - last_transfer[id][1] <= 0: continue dt_transfer[id] = [curr_transfer[id][0] - last_transfer[id][0], curr_transfer[id][1] - last_transfer[id][1]] else: if curr_transfer[id][0] + curr_transfer[id][1] <= 0: continue dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] #有流量的,先记录在线状态 if id in self.last_get_transfer: if curr_transfer[id][0] + curr_transfer[id][1] > self.last_get_transfer[id][0] + self.last_get_transfer[id][1]: self.onlineuser_cache[id] = curr_transfer[id][0] + curr_transfer[id][1] else: self.onlineuser_cache[id] = curr_transfer[id][0] + curr_transfer[id][1] self.onlineuser_cache.sweep() update_transfer = self.update_all_user(dt_transfer) #返回有更新的表 for id in update_transfer.keys(): #其增量加在此表 if id not in self.force_update_transfer: #但排除在force_update_transfer内的 last = self.last_update_transfer.get(id, [0,0]) self.last_update_transfer[id] = [last[0] + update_transfer[id][0], last[1] + update_transfer[id][1]] self.last_get_transfer = curr_transfer for id in self.force_update_transfer: if id in self.last_update_transfer: del self.last_update_transfer[id] if id in self.last_get_transfer: del self.last_get_transfer[id] self.force_update_transfer = set()
def render_GET(self, request): retcode = 1 retmsg = 'unknow err' if request.uri.startswith('/cmd/del_server'): while True: try: if not 'key' in request.args or Config.REST_APIKEY != request.args['key'][0]: retmsg = 'key error' break port = int(request.args['port'][0]) if ServerPool.get_instance().del_server(port) is True: retcode = 0 retmsg = 'success' except Exception, e: retmsg = str(e) finally: break
def push_db_all_user(self): if self.pull_ok is False: return #更新用户流量到数据库 last_transfer = self.last_update_transfer curr_transfer = ServerPool.get_instance().get_servers_transfer() #上次和本次的增量 dt_transfer = {} for id in curr_transfer.keys(): if id in last_transfer: if curr_transfer[id][0] + curr_transfer[id][1] - last_transfer[ id][0] - last_transfer[id][1] <= 0: continue if last_transfer[id][0] <= curr_transfer[id][0] and \ last_transfer[id][1] <= curr_transfer[id][1]: dt_transfer[id] = [ curr_transfer[id][0] - last_transfer[id][0], curr_transfer[id][1] - last_transfer[id][1] ] else: dt_transfer[id] = [ curr_transfer[id][0], curr_transfer[id][1] ] else: if curr_transfer[id][0] + curr_transfer[id][1] <= 0: continue dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] if id in self.last_get_transfer: if curr_transfer[id][0] + curr_transfer[id][ 1] > self.last_get_transfer[id][ 0] + self.last_get_transfer[id][1]: self.onlineuser_cache[ id] = curr_transfer[id][0] + curr_transfer[id][1] else: self.onlineuser_cache[ id] = curr_transfer[id][0] + curr_transfer[id][1] self.onlineuser_cache.sweep() update_transfer = self.update_all_user(dt_transfer) for id in update_transfer.keys(): last = self.last_update_transfer.get(id, [0, 0]) self.last_update_transfer[id] = [ last[0] + update_transfer[id][0], last[1] + update_transfer[id][1] ] self.last_get_transfer = curr_transfer
def del_server(self, port, reason): logging.info('db stop server at port [%s] reason: %s!' % (port, reason)) ServerPool.get_instance().cb_del_server(port) if port in self.last_update_transfer: del self.last_update_transfer[port] for mu_user_port in self.mu_port_list: if mu_user_port in ServerPool.get_instance().tcp_servers_pool: ServerPool.get_instance().tcp_servers_pool[ mu_user_port].reset_single_multi_user_traffic( self.port_uid_table[port]) #if mu_user_port in ServerPool.get_instance().tcp_ipv6_servers_pool: # ServerPool.get_instance().tcp_ipv6_servers_pool[ # mu_user_port].reset_single_multi_user_traffic(self.port_uid_table[port]) if mu_user_port in ServerPool.get_instance().udp_servers_pool: ServerPool.get_instance().udp_servers_pool[ mu_user_port].reset_single_multi_user_traffic( self.port_uid_table[port])
def del_server_out_of_bound_safe(rows): #停止超流量的服务 #启动没超流量的服务 for row in rows: if ServerPool.get_instance().server_is_run(row[0]) > 0: if ((row[1] + row[2] >= row[3]) or (row[5] == 0)): logging.info('db stop server at port [%s]' % (row[0])) ServerPool.get_instance().del_server(row[0]) elif ServerPool.get_instance().server_run_status(row[0]) is False: if row[5] == 1 and row[1] + row[2] < row[3]: logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4])
def del_server_out_of_bound_safe(rows): #停止超流量的服务 #启动没超流量的服务 for row in rows: if ServerPool.get_instance().server_is_run(row['port']) > 0: if row['u'] + row['d'] >= row['transfer_enable'] or (not row['enable']): logging.info('db stop server at port [%s]' % (row['port'])) ServerPool.get_instance().del_server(row['port']) elif ServerPool.get_instance().server_run_status(row['port']) is False: if row['switch'] and row['enable'] and row['u'] + row['d'] < row['transfer_enable']: logging.info('db start server at port [%s] pass [%s]' % (row['port'], row['passwd'])) ServerPool.get_instance().new_server(row['port'], row['passwd'])
def del_server_out_of_bound_safe(rows): #停止超流量的服务 #启动没超流量的服务 for row in rows: if ServerPool.get_instance().server_is_run(row[0]) > 0: if row[1] + row[2] >= row[3]: logging.info('db stop server at port [%s]' % (row[0])) ServerPool.get_instance().del_server(row[0]) elif ServerPool.get_instance().server_run_status(row[0]) is False: if row[5] == 1 and row[6] == 1 and row[1] + row[2] < row[3]: logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4])
def render_GET(self, request): retcode = 1 retmsg = 'unknow err' if request.uri.startswith('/cmd/del_server'): while True: try: if not 'key' in request.args or Config.REST_APIKEY != request.args[ 'key'][0]: retmsg = 'key error' break port = int(request.args['port'][0]) if ServerPool.get_instance().del_server(port) is True: retcode = 0 retmsg = 'success' except Exception, e: retmsg = str(e) finally: break
def del_server_out_of_bound_safe(rows): #停止超流量的服务 #启动没超流量的服务 for row in rows: if ServerPool.get_instance().server_is_run(row[0]) > 0: if datetime.datetime.now() >= row[7]: #if row[1] + row[2] >= row[3] and lasttime >= row[7]: logging.info('db stop server at port [%s]' % (row[0])) ServerPool.get_instance().del_server(row[0]) elif ServerPool.get_instance().server_run_status(row[0]) is False: if row[5] == 1 and row[6] == 1 and datetime.datetime.now() < row[7]: logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4])
def del_server_out_of_bound_safe(rows, mids): #停止超流量的服务 #启动没超流量的服务 port_is_running = [] for row in rows: if ServerPool.get_instance().server_is_run(row[0]) > 0: if row[1] + row[2] >= row[3] or row[5] != 1 or row[7] not in mids: logging.info('db stop server at port [%s]' % (row[0])) #原来这里使用的是del_server方法,不适用,无法进行删除,修改成cb_del_server后可行 ServerPool.get_instance().cb_del_server(row[0]) else: port_is_running.append(row[0]) elif ServerPool.get_instance().server_run_status(row[0]) is False: if row[5] == 1 and row[1] + row[2] < row[3] and row[7] in mids: logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4]) return port_is_running
def stop_or_start_server(self, user): port = int(user['port']) if hasattr(user['password'], 'encode'): user['password'] = user['password'].encode('utf-8') password = user['password'] is_run = ServerPool.get_instance().server_is_run(port) old_password = self._users[port].get('password', None) if is_run and user['isLocked']: logging.info('stop server at port [%s] reason: disable' % (port)) ServerPool.get_instance().del_server(port) elif is_run and old_password != password: logging.info('stop server at port [%s] reason: password changed' % (port)) ServerPool.get_instance().del_server(port) elif not is_run and not user['isLocked']: logging.info('start server at port [%s] pass [%s]' % (port, password)) ServerPool.get_instance().add_server({ 'server_port': port, 'password': password }) self._users[port] = user
def del_server_out_of_bound_safe(rows): """ #增加了检查用户类型 #增加了检用服务器类型,只有服务器类型与当用vip类型一致才启动服务 #停止超流量的服务 #启动没超流量的服务 #增加试用的逻辑 -9 if int(row[7]) != Config.SERVER_TYPE or ( (row[7] > 1 and row[1] + row[2] >= row[3] ) or row[6] != 1): if int(row[7]) == Config.SERVER_TYPE and ( row[5] == 1 and row[6] == 1 and ( row[1] + row[2] < row[3] and row[7] > 1)): """ for row in rows: if ServerPool.get_instance().server_is_run(row[0]) > 0: if row[6] != -9 and row[6] != 1: logging.info('db stop server at port [%s]' % (row[0])) ServerPool.get_instance().del_server(row[0]) elif ServerPool.get_instance().server_run_status(row[0]) is False: if row[6] == -9 or row[6] == 1: logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4])
def del_server_out_of_bound_safe(self, last_rows, rows): #停止超流量的服务 #启动没超流量的服务 #需要动态载入switchrule,以便实时修改规则 try: switchrule = importloader.load('switchrule') except Exception as e: logging.error('load switchrule.py fail') cur_servers = {} new_servers = {} md5_users = {} for row in rows: if row['is_multi_user'] == 1: continue md5_users[row['id']] = row.copy() del md5_users[row['id']]['u'] del md5_users[row['id']]['d'] if md5_users[row['id']]['disconnect_ip'] == None: md5_users[row['id']]['disconnect_ip'] = '' if md5_users[row['id']]['forbidden_ip'] == None: md5_users[row['id']]['forbidden_ip'] = '' if md5_users[row['id']]['forbidden_port'] == None: md5_users[row['id']]['forbidden_port'] = '' md5_users[row['id']]['md5'] = common.get_md5(str(row['id']) + row['passwd'] + row['method'] + row['obfs'] + row['protocol']) for row in rows: port = row['port'] passwd = common.to_bytes(row['passwd']) cfg = {'password': passwd} self.port_uid_table[row['port']] = row['id'] self.uid_port_table[row['id']] = row['port'] read_config_keys = ['method', 'obfs','obfs_param' , 'protocol', 'protocol_param' ,'forbidden_ip', 'forbidden_port' , 'node_speedlimit','forbidden_ip','forbidden_port','disconnect_ip','is_multi_user'] for name in read_config_keys: if name in row and row[name]: cfg[name] = row[name] merge_config_keys = ['password'] + read_config_keys for name in cfg.keys(): if hasattr(cfg[name], 'encode'): cfg[name] = cfg[name].encode('utf-8') if 'node_speedlimit' in cfg: if float(self.node_speedlimit) > 0.0 or float(cfg['node_speedlimit']) > 0.0 : cfg['node_speedlimit'] = max(float(self.node_speedlimit),float(cfg['node_speedlimit'])) else: cfg['node_speedlimit'] = max(float(self.node_speedlimit),float(0.00)) if 'disconnect_ip' not in cfg: cfg['disconnect_ip'] = '' if 'forbidden_ip' not in cfg: cfg['forbidden_ip'] = '' if 'forbidden_port' not in cfg: cfg['forbidden_port'] = '' if 'protocol_param' not in cfg: cfg['protocol_param'] = '' if 'obfs_param' not in cfg: cfg['obfs_param'] = '' if 'is_multi_user' not in cfg: cfg['is_multi_user'] = 0 if port not in cur_servers: cur_servers[port] = passwd else: logging.error('more than one user use the same port [%s]' % (port,)) continue if get_config().MULTI_THREAD == 0: cfg['node_speedlimit'] = 0.00 cfg['detect_text_list'] = self.detect_text_list.copy() cfg['detect_hex_list'] = self.detect_hex_list.copy() if cfg['is_multi_user'] == 1: cfg['users_table'] = md5_users.copy() if ServerPool.get_instance().server_is_run(port) > 0: cfgchange = False if self.detect_text_ischanged == True or self.detect_hex_ischanged == True: cfgchange = True if row['is_multi_user'] == 1: if port in ServerPool.get_instance().tcp_servers_pool: ServerPool.get_instance().tcp_servers_pool[port].modify_multi_user_table(md5_users) if port in ServerPool.get_instance().tcp_ipv6_servers_pool: ServerPool.get_instance().tcp_ipv6_servers_pool[port].modify_multi_user_table(md5_users) if port in ServerPool.get_instance().udp_servers_pool: ServerPool.get_instance().udp_servers_pool[port].modify_multi_user_table(md5_users) if port in ServerPool.get_instance().udp_ipv6_servers_pool: ServerPool.get_instance().udp_ipv6_servers_pool[port].modify_multi_user_table(md5_users) if port in ServerPool.get_instance().tcp_servers_pool: relay = ServerPool.get_instance().tcp_servers_pool[port] for name in merge_config_keys: if name in cfg and not self.cmp(cfg[name], relay._config[name]): cfgchange = True break; if not cfgchange and port in ServerPool.get_instance().tcp_ipv6_servers_pool: relay = ServerPool.get_instance().tcp_ipv6_servers_pool[port] for name in merge_config_keys: if name in cfg and not self.cmp(cfg[name], relay._config[name]): cfgchange = True break; #config changed if cfgchange: logging.info('db stop server at port [%s] reason: config changed!' % (port)) ServerPool.get_instance().cb_del_server(port) if port in self.last_update_transfer: del self.last_update_transfer[port] new_servers[port] = (passwd, cfg) elif ServerPool.get_instance().server_run_status(port) is False: #new_servers[port] = passwd protocol = cfg.get('protocol', ServerPool.get_instance().config.get('protocol', 'origin')) obfs = cfg.get('obfs', ServerPool.get_instance().config.get('obfs', 'plain')) logging.info('db start server at port [%s] pass [%s] protocol [%s] obfs [%s]' % (port, passwd, protocol, obfs)) ServerPool.get_instance().new_server(port, cfg) ServerPool.get_instance().push_uid_port_table(self.uid_port_table) for row in last_rows: if row['port'] in cur_servers: pass else: logging.info('db stop server at port [%s] reason: port not exist' % (row['port'])) ServerPool.get_instance().cb_del_server(row['port']) if row['port'] in self.last_update_transfer: del self.last_update_transfer[row['port']] del self.port_uid_table[row['port']] if len(new_servers) > 0: from shadowsocks import eventloop self.event.wait(eventloop.TIMEOUT_PRECISION + eventloop.TIMEOUT_PRECISION / 2) for port in new_servers.keys(): passwd, cfg = new_servers[port] protocol = cfg.get('protocol', ServerPool.get_instance().config.get('protocol', 'origin')) obfs = cfg.get('obfs', ServerPool.get_instance().config.get('obfs', 'plain')) logging.info('db start server at port [%s] pass [%s] protocol [%s] obfs [%s]' % (port, passwd, protocol, obfs)) self.port_uid_table[row['port']] = row['id'] ServerPool.get_instance().new_server(port, cfg)
def push_db_all_user(self): #更新用户流量到数据库 last_transfer = self.last_get_transfer curr_transfer = ServerPool.get_instance().get_servers_transfer() #上次和本次的增量 dt_transfer = {} for id in curr_transfer.keys(): if id in last_transfer: if last_transfer[id][0] == curr_transfer[id][0] and last_transfer[id][1] == curr_transfer[id][1]: continue elif curr_transfer[id][0] == 0 and curr_transfer[id][1] == 0: continue elif last_transfer[id][0] <= curr_transfer[id][0] and \ last_transfer[id][1] <= curr_transfer[id][1]: dt_transfer[id] = [curr_transfer[id][0] - last_transfer[id][0], curr_transfer[id][1] - last_transfer[id][1]] else: dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] else: if curr_transfer[id][0] == 0 and curr_transfer[id][1] == 0: continue dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] self.last_get_transfer = curr_transfer query_head = 'UPDATE user' query_sub_when = '' query_sub_when2 = '' query_sub_when3 = '' query_sub_when4 = '' query_sub_when5 = '' query_sub_when6 = '' query_sub_in = None last_time = time.time() for id in dt_transfer.keys(): query_sub_when += ' WHEN %s THEN u+%s' % (id, dt_transfer[id][0]) query_sub_when2 += ' WHEN %s THEN d+%s' % (id, dt_transfer[id][1]) query_sub_when3 += ' WHEN %s THEN month_u+%s' % (id, dt_transfer[id][0]) query_sub_when4 += ' WHEN %s THEN month_d+%s' % (id, dt_transfer[id][1]) query_sub_when5 += ' WHEN %s THEN sign_u+%s' % (id, dt_transfer[id][0]) query_sub_when6 += ' WHEN %s THEN sign_d+%s' % (id, dt_transfer[id][1]) if query_sub_in is not None: query_sub_in += ',%s' % id else: query_sub_in = '%s' % id if query_sub_when == '' and query_sub_when3 == '' and query_sub_when5== '': return query_sql = query_head + ' SET u = CASE port' + query_sub_when + \ ' END, d = CASE port' + query_sub_when2 + \ ' END, t = ' + str(int(last_time)) + \ ',last_login_server_id = ' +str(int(Config.SERVER_ID)) + \ ' WHERE service_type in (0,3) and port IN (%s)' % query_sub_in query_sql2 = query_head + ' SET month_u = CASE port' + query_sub_when3 + \ ' END, month_d = CASE port' + query_sub_when4 + \ ' END, t = ' + str(int(last_time)) + \ ',last_login_server_id = ' +str(int(Config.SERVER_ID)) + \ ' WHERE service_type in (1,2) and port IN (%s)' % query_sub_in query_sql3 = query_head + ' SET sign_u = CASE port' + query_sub_when5 + \ ' END, sign_d = CASE port' + query_sub_when6 + \ ' END, t = ' + str(int(last_time)) + \ ',last_login_server_id = ' +str(int(Config.SERVER_ID)) + \ ' WHERE service_type = 0 and port IN (%s)' % query_sub_in #print query_sql conn = cymysql.connect(host=Config.MYSQL_HOST, port=Config.MYSQL_PORT, user=Config.MYSQL_USER, passwd=Config.MYSQL_PASS, db=Config.MYSQL_DB, charset='utf8') cur = conn.cursor() cur.execute(query_sql) cur.execute(query_sql2) if Config.SERVER_TYPE=='SIGN' : cur.execute(query_sql3) cur.close() conn.commit() conn.close()
def del_server_out_of_bound_safe(last_rows, rows): #停止超流量的服务 #启动没超流量的服务 #需要动态载入switchrule,以便实时修改规则 try: import switchrule reload(switchrule) except Exception as e: logging.error('load switchrule.py fail') cur_servers = {} new_servers = {} for row in rows: try: allow = switchrule.isTurnOn(row) and row['enable'] == 1 and row['flow_up'] + row['flow_up'] < row['transfer'] except Exception as e: allow = False port = row['port'] passwd = common.to_bytes(row['sspwd']) plan = row['plan'] if port not in cur_servers: cur_servers[port] = passwd else: logging.error('more than one user use the same port [%s]' % (port,)) continue if ServerPool.get_instance().server_is_run(port) > 0: if not allow: logging.info('db stop server at port [%s]' % (port,)) ServerPool.get_instance().cb_del_server(port) elif (port in ServerPool.get_instance().tcp_servers_pool and ServerPool.get_instance().tcp_servers_pool[port]._config['password'] != passwd) \ or (port in ServerPool.get_instance().tcp_ipv6_servers_pool and ServerPool.get_instance().tcp_ipv6_servers_pool[port]._config['password'] != passwd): #password changed logging.info('db stop server at port [%s] reason: password changed' % (port,)) ServerPool.get_instance().cb_del_server(port) new_servers[port] = passwd elif Config.PRO_NODE and plan!='VIP': logging.info('db stop server at port [%s] reason: not VIP plan' % (port,)) ServerPool.get_instance().cb_del_server(port) elif allow and ServerPool.get_instance().server_run_status(port) is False: if Config.PRO_NODE and plan!='VIP': pass else: #new_servers[port] = passwd logging.info('db start server at port [%s] pass [%s]' % (port, passwd)) ServerPool.get_instance().new_server(port, passwd) for row in last_rows: if row['port'] in cur_servers: pass else: logging.info('db stop server at port [%s] reason: port not exist' % (row['port'])) ServerPool.get_instance().cb_del_server(row['port']) if len(new_servers) > 0: from shadowsocks import eventloop DbTransfer.get_instance().event.wait(eventloop.TIMEOUT_PRECISION) for port in new_servers.keys(): logging.info(plan) passwd = new_servers[port] logging.info('db start server at port [%s] pass [%s]' % (port, passwd)) ServerPool.get_instance().new_server(port, passwd)
def is_all_thread_alive(self): if not ServerPool.get_instance().thread.is_alive(): return False return True
def update_all_user(self, dt_transfer): global webapi update_transfer = {} alive_user_count = 0 bandwidth_thistime = 0 data = [] for id in dt_transfer.keys(): if dt_transfer[id][0] == 0 and dt_transfer[id][1] == 0: continue data.append({ 'u': dt_transfer[id][0], 'd': dt_transfer[id][1], 'user_id': self.port_uid_table[id] }) update_transfer[id] = dt_transfer[id] webapi.postApi('users/traffic', {'node_id': get_config().NODE_ID}, {'data': data}) webapi.postApi('nodes/%d/info' % (get_config().NODE_ID), {'node_id': get_config().NODE_ID}, { 'uptime': str(self.uptime()), 'load': str(self.load()) }) online_iplist = ServerPool.get_instance().get_servers_iplist() data = [] for port in online_iplist.keys(): for ip in online_iplist[port]: data.append({'ip': ip, 'user_id': self.port_uid_table[port]}) webapi.postApi('users/aliveip', {'node_id': get_config().NODE_ID}, {'data': data}) detect_log_list = ServerPool.get_instance().get_servers_detect_log() data = [] for port in detect_log_list.keys(): for rule_id in detect_log_list[port]: data.append({ 'list_id': rule_id, 'user_id': self.port_uid_table[port] }) webapi.postApi('users/detectlog', {'node_id': get_config().NODE_ID}, {'data': data}) deny_str = "" data = [] if platform.system() == 'Linux' and get_config().ANTISSATTACK == 1: wrong_iplist = ServerPool.get_instance().get_servers_wrong() server_ip = socket.gethostbyname(get_config().MYSQL_HOST) for id in wrong_iplist.keys(): for ip in wrong_iplist[id]: realip = "" is_ipv6 = False if common.is_ip(ip): if (common.is_ip(ip) == socket.AF_INET): realip = ip else: if common.match_ipv4_address(ip) is not None: realip = common.match_ipv4_address(ip) else: is_ipv6 = True realip = ip else: continue if str(realip).find(str(server_ip)) != -1: continue has_match_node = False for node_ip in self.node_ip_list: if str(realip).find(node_ip) != -1: has_match_node = True continue if has_match_node: continue if get_config().CLOUDSAFE == 1: data.append({'ip': realip}) else: if not is_ipv6: os.system('route add -host %s gw 127.0.0.1' % str(realip)) deny_str = deny_str + "\nALL: " + str(realip) else: os.system('ip -6 route add ::1/128 via %s/128' % str(realip)) deny_str = deny_str + \ "\nALL: [" + str(realip) + "]/128" logging.info("Local Block ip:" + str(realip)) if get_config().CLOUDSAFE == 0: deny_file = open('/etc/hosts.deny', 'a') fcntl.flock(deny_file.fileno(), fcntl.LOCK_EX) deny_file.write(deny_str) deny_file.close() webapi.postApi('func/block_ip', {'node_id': get_config().NODE_ID}, {'data': data}) return update_transfer
def del_server_out_of_bound_safe(self, last_rows, rows): # 停止超流量的服务 # 启动没超流量的服务 # 需要动态载入switchrule,以便实时修改规则 try: switchrule = importloader.load('switchrule') except Exception as e: logging.error('load switchrule.py fail') cur_servers = {} new_servers = {} md5_users = {} self.mu_port_list = [] for row in rows: if row['is_multi_user'] != 0: self.mu_port_list.append(int(row['port'])) continue md5_users[row['id']] = row.copy() del md5_users[row['id']]['u'] del md5_users[row['id']]['d'] if md5_users[row['id']]['disconnect_ip'] is None: md5_users[row['id']]['disconnect_ip'] = '' if md5_users[row['id']]['forbidden_ip'] is None: md5_users[row['id']]['forbidden_ip'] = '' if md5_users[row['id']]['forbidden_port'] is None: md5_users[row['id']]['forbidden_port'] = '' md5_users[row['id']]['md5'] = common.get_md5( str(row['id']) + row['passwd'] + row['method'] + row['obfs'] + row['protocol']) for row in rows: self.port_uid_table[row['port']] = row['id'] self.uid_port_table[row['id']] = row['port'] if self.mu_only == 1 or self.mu_only == 2: i = 0 while i < len(rows): if rows[i]['is_multi_user'] == 0: rows.pop(i) i -= 1 else: pass i += 1 if self.mu_only == -1: i = 0 while i < len(rows): if rows[i]['is_multi_user'] != 0: rows.pop(i) i -= 1 else: pass i += 1 for row in rows: port = row['port'] user_id = row['id'] passwd = common.to_bytes(row['passwd']) cfg = {'password': passwd} read_config_keys = [ 'method', 'obfs', 'obfs_param', 'protocol', 'protocol_param', 'forbidden_ip', 'forbidden_port', 'node_speedlimit', 'disconnect_ip', 'is_multi_user' ] for name in read_config_keys: if name in row and row[name]: cfg[name] = row[name] merge_config_keys = ['password'] + read_config_keys for name in cfg.keys(): if hasattr(cfg[name], 'encode'): try: cfg[name] = cfg[name].encode('utf-8') except Exception as e: logging.warning('encode cfg key "%s" fail, val "%s"' % (name, cfg[name])) if 'node_speedlimit' in cfg: if float(self.node_speedlimit) > 0.0 or float( cfg['node_speedlimit']) > 0.0: cfg['node_speedlimit'] = max(float(self.node_speedlimit), float(cfg['node_speedlimit'])) else: cfg['node_speedlimit'] = max(float(self.node_speedlimit), float(0.00)) if 'disconnect_ip' not in cfg: cfg['disconnect_ip'] = '' if 'forbidden_ip' not in cfg: cfg['forbidden_ip'] = '' if 'forbidden_port' not in cfg: cfg['forbidden_port'] = '' if 'protocol_param' not in cfg: cfg['protocol_param'] = '' if 'obfs_param' not in cfg: cfg['obfs_param'] = '' if 'is_multi_user' not in cfg: cfg['is_multi_user'] = 0 if port not in cur_servers: cur_servers[port] = passwd else: logging.error('more than one user use the same port [%s]' % (port, )) continue if cfg['is_multi_user'] != 0: cfg['users_table'] = md5_users.copy() cfg['detect_hex_list'] = self.detect_hex_list.copy() cfg['detect_text_list'] = self.detect_text_list.copy() if self.is_relay and row['is_multi_user'] != 2: temp_relay_rules = {} for id in self.relay_rule_list: if ((self.relay_rule_list[id]['user_id'] == user_id or self.relay_rule_list[id]['user_id'] == 0) or row['is_multi_user'] != 0) and ( self.relay_rule_list[id]['port'] == 0 or self.relay_rule_list[id]['port'] == port): has_higher_priority = False for priority_id in self.relay_rule_list: if ( (self.relay_rule_list[priority_id]['priority'] > self.relay_rule_list[id]['priority'] and self.relay_rule_list[id]['id'] != self.relay_rule_list[priority_id]['id']) or (self.relay_rule_list[priority_id]['priority'] == self.relay_rule_list[id]['priority'] and self.relay_rule_list[id]['id'] > self.relay_rule_list[priority_id]['id']) ) and (self.relay_rule_list[priority_id]['user_id'] == user_id or self.relay_rule_list[priority_id]['user_id'] == 0) and (self.relay_rule_list[priority_id] ['port'] == port or self.relay_rule_list[priority_id] ['port'] == 0): has_higher_priority = True continue if has_higher_priority: continue if self.relay_rule_list[id][ 'dist_ip'] == '0.0.0.0' and row[ 'is_multi_user'] == 0: continue temp_relay_rules[id] = self.relay_rule_list[id] cfg['relay_rules'] = temp_relay_rules.copy() else: temp_relay_rules = {} cfg['relay_rules'] = temp_relay_rules.copy() if ServerPool.get_instance().server_is_run(port) > 0: cfgchange = False if port in ServerPool.get_instance().tcp_servers_pool: ServerPool.get_instance( ).tcp_servers_pool[port].modify_detect_text_list( self.detect_text_list) ServerPool.get_instance( ).tcp_servers_pool[port].modify_detect_hex_list( self.detect_hex_list) if port in ServerPool.get_instance().tcp_ipv6_servers_pool: ServerPool.get_instance( ).tcp_ipv6_servers_pool[port].modify_detect_text_list( self.detect_text_list) ServerPool.get_instance( ).tcp_ipv6_servers_pool[port].modify_detect_hex_list( self.detect_hex_list) if port in ServerPool.get_instance().udp_servers_pool: ServerPool.get_instance( ).udp_servers_pool[port].modify_detect_text_list( self.detect_text_list) ServerPool.get_instance( ).udp_servers_pool[port].modify_detect_hex_list( self.detect_hex_list) if port in ServerPool.get_instance().udp_ipv6_servers_pool: ServerPool.get_instance( ).udp_ipv6_servers_pool[port].modify_detect_text_list( self.detect_text_list) ServerPool.get_instance( ).udp_ipv6_servers_pool[port].modify_detect_hex_list( self.detect_hex_list) if row['is_multi_user'] != 0: if port in ServerPool.get_instance().tcp_servers_pool: ServerPool.get_instance().tcp_servers_pool[ port].modify_multi_user_table(md5_users) if port in ServerPool.get_instance().tcp_ipv6_servers_pool: ServerPool.get_instance().tcp_ipv6_servers_pool[ port].modify_multi_user_table(md5_users) if port in ServerPool.get_instance().udp_servers_pool: ServerPool.get_instance().udp_servers_pool[ port].modify_multi_user_table(md5_users) if port in ServerPool.get_instance().udp_ipv6_servers_pool: ServerPool.get_instance().udp_ipv6_servers_pool[ port].modify_multi_user_table(md5_users) if self.is_relay and row['is_multi_user'] != 2: temp_relay_rules = {} for id in self.relay_rule_list: if ((self.relay_rule_list[id]['user_id'] == user_id or self.relay_rule_list[id]['user_id'] == 0) or row['is_multi_user'] != 0) and ( self.relay_rule_list[id]['port'] == 0 or self.relay_rule_list[id]['port'] == port): has_higher_priority = False for priority_id in self.relay_rule_list: if ((self.relay_rule_list[priority_id] ['priority'] > self.relay_rule_list[id]['priority'] and self.relay_rule_list[id]['id'] != self.relay_rule_list[priority_id]['id']) or (self.relay_rule_list[priority_id] ['priority'] == self.relay_rule_list[id]['priority'] and self.relay_rule_list[id]['id'] > self. relay_rule_list[priority_id]['id'])) and ( self.relay_rule_list[priority_id] ['user_id'] == user_id or self.relay_rule_list[priority_id] ['user_id'] == 0) and ( self.relay_rule_list[priority_id] ['port'] == port or self.relay_rule_list[priority_id] ['port'] == 0): has_higher_priority = True continue if has_higher_priority: continue if self.relay_rule_list[id][ 'dist_ip'] == '0.0.0.0' and row[ 'is_multi_user'] == 0: continue temp_relay_rules[id] = self.relay_rule_list[id] if port in ServerPool.get_instance().tcp_servers_pool: ServerPool.get_instance().tcp_servers_pool[ port].push_relay_rules(temp_relay_rules) if port in ServerPool.get_instance().tcp_ipv6_servers_pool: ServerPool.get_instance().tcp_ipv6_servers_pool[ port].push_relay_rules(temp_relay_rules) if port in ServerPool.get_instance().udp_servers_pool: ServerPool.get_instance().udp_servers_pool[ port].push_relay_rules(temp_relay_rules) if port in ServerPool.get_instance().udp_ipv6_servers_pool: ServerPool.get_instance().udp_ipv6_servers_pool[ port].push_relay_rules(temp_relay_rules) else: temp_relay_rules = {} if port in ServerPool.get_instance().tcp_servers_pool: ServerPool.get_instance().tcp_servers_pool[ port].push_relay_rules(temp_relay_rules) if port in ServerPool.get_instance().tcp_ipv6_servers_pool: ServerPool.get_instance().tcp_ipv6_servers_pool[ port].push_relay_rules(temp_relay_rules) if port in ServerPool.get_instance().udp_servers_pool: ServerPool.get_instance().udp_servers_pool[ port].push_relay_rules(temp_relay_rules) if port in ServerPool.get_instance().udp_ipv6_servers_pool: ServerPool.get_instance().udp_ipv6_servers_pool[ port].push_relay_rules(temp_relay_rules) if port in ServerPool.get_instance().tcp_servers_pool: relay = ServerPool.get_instance().tcp_servers_pool[port] for name in merge_config_keys: if name in cfg and not self.cmp( cfg[name], relay._config[name]): cfgchange = True break if not cfgchange and port in ServerPool.get_instance( ).tcp_ipv6_servers_pool: relay = ServerPool.get_instance( ).tcp_ipv6_servers_pool[port] for name in merge_config_keys: if name in cfg and not self.cmp( cfg[name], relay._config[name]): cfgchange = True break # config changed if cfgchange: self.del_server(port, "config changed") new_servers[port] = (passwd, cfg) elif ServerPool.get_instance().server_run_status(port) is False: # new_servers[port] = passwd self.new_server(port, passwd, cfg) for row in last_rows: if row['port'] in cur_servers: pass else: self.del_server(row['port'], "port not exist") if len(new_servers) > 0: from shadowsocks import eventloop self.event.wait(eventloop.TIMEOUT_PRECISION + eventloop.TIMEOUT_PRECISION / 2) for port in new_servers.keys(): passwd, cfg = new_servers[port] self.new_server(port, passwd, cfg) ServerPool.get_instance().push_uid_port_table(self.uid_port_table)
try: import switchrule except Exception, e: logging.error('load switchrule.py fail') cur_servers = {} for row in rows: try: allow = switchrule.isTurnOn(row) and row['enable'] == 1 and row['u'] + row['d'] < row['transfer_enable'] except Exception, e: allow = False port = row['port'] passwd = row['passwd'] cur_servers[port] = passwd if ServerPool.get_instance().server_is_run(port) > 0: if not allow: logging.info('db stop server at port [%s]' % (port,)) ServerPool.get_instance().del_server(port) elif (port in ServerPool.get_instance().tcp_servers_pool and ServerPool.get_instance().tcp_servers_pool[port]._config['password'] != passwd) \ or (port in ServerPool.get_instance().tcp_ipv6_servers_pool and ServerPool.get_instance().tcp_ipv6_servers_pool[port]._config['password'] != passwd): #password changed logging.info('db stop server at port [%s] reason: password changed' % (port,)) ServerPool.get_instance().del_server(port) elif allow and ServerPool.get_instance().server_run_status(port) is False: logging.info('db start server at port [%s] pass [%s]' % (port, passwd)) ServerPool.get_instance().new_server(port, passwd) for row in last_rows: if row['port'] in cur_servers:
def del_server_out_of_bound_safe(self, last_rows, rows): #停止超流量的服务 #启动没超流量的服务 try: switchrule = importloader.load('switchrule') except Exception as e: logging.error('load switchrule.py fail') cur_servers = {} new_servers = {} for row in rows: try: allow = switchrule.isTurnOn(row) and row['enable'] == 1 and row['u'] + row['d'] < row['transfer_enable'] except Exception as e: allow = False port = row['port'] passwd = common.to_bytes(row['passwd']) cfg = {'password': passwd} if 'id' in row: self.port_uid_table[row['port']] = row['id'] read_config_keys = ['method', 'obfs', 'obfs_param', 'protocol', 'protocol_param', 'forbidden_ip', 'forbidden_port'] for name in read_config_keys: if name in row and row[name]: cfg[name] = row[name] merge_config_keys = ['password'] + read_config_keys for name in cfg.keys(): if hasattr(cfg[name], 'encode'): cfg[name] = cfg[name].encode('utf-8') if port not in cur_servers: cur_servers[port] = passwd else: logging.error('more than one user use the same port [%s]' % (port,)) continue if ServerPool.get_instance().server_is_run(port) > 0: if not allow: logging.info('db stop server at port [%s]' % (port,)) ServerPool.get_instance().cb_del_server(port) self.force_update_transfer.add(port) else: cfgchange = False if port in ServerPool.get_instance().tcp_servers_pool: relay = ServerPool.get_instance().tcp_servers_pool[port] for name in merge_config_keys: if name in cfg and not self.cmp(cfg[name], relay._config[name]): cfgchange = True break; if not cfgchange and port in ServerPool.get_instance().tcp_ipv6_servers_pool: relay = ServerPool.get_instance().tcp_ipv6_servers_pool[port] for name in merge_config_keys: if name in cfg and not self.cmp(cfg[name], relay._config[name]): cfgchange = True break; #config changed if cfgchange: logging.info('db stop server at port [%s] reason: config changed: %s' % (port, cfg)) ServerPool.get_instance().cb_del_server(port) self.force_update_transfer.add(port) new_servers[port] = (passwd, cfg) elif allow and ServerPool.get_instance().server_run_status(port) is False: self.new_server(port, passwd, cfg) for row in last_rows: if row['port'] in cur_servers: pass else: logging.info('db stop server at port [%s] reason: port not exist' % (row['port'])) ServerPool.get_instance().cb_del_server(row['port']) self.clear_cache(row['port']) if row['port'] in self.port_uid_table: del self.port_uid_table[row['port']] if len(new_servers) > 0: from shadowsocks import eventloop self.event.wait(eventloop.TIMEOUT_PRECISION + eventloop.TIMEOUT_PRECISION / 2) for port in new_servers.keys(): passwd, cfg = new_servers[port] self.new_server(port, passwd, cfg)
def push_db_all_user(self): # 更新用户流量到数据库 last_transfer = self.last_get_transfer curr_transfer = ServerPool.get_instance().get_servers_transfer() # 上次和本次的增量 dt_transfer = {} for id in curr_transfer.keys(): if id in last_transfer: if last_transfer[id][0] == curr_transfer[id][0] and last_transfer[id][1] == curr_transfer[id][1]: continue elif curr_transfer[id][0] == 0 and curr_transfer[id][1] == 0: continue elif last_transfer[id][0] <= curr_transfer[id][0] and last_transfer[id][1] <= curr_transfer[id][1]: dt_transfer[id] = [ curr_transfer[id][0] - last_transfer[id][0], curr_transfer[id][1] - last_transfer[id][1], ] else: dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] # else: # if curr_transfer[id][0] == 0 and curr_transfer[id][1] == 0: # continue # dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] self.last_get_transfer = curr_transfer query_head = "UPDATE user" query_sub_when = "" query_sub_when2 = "" query_sub_in = None last_time = time.time() for id in dt_transfer.keys(): query_sub_when += " WHEN %s THEN u+%s" % (id, dt_transfer[id][0]) query_sub_when2 += " WHEN %s THEN d+%s" % (id, dt_transfer[id][1]) if query_sub_in is not None: query_sub_in += ",%s" % id else: query_sub_in = "%s" % id if query_sub_when == "": return query_sql = ( query_head + " SET u = CASE port" + query_sub_when + " END, d = CASE port" + query_sub_when2 + " END, t = " + str(int(last_time)) + " WHERE port IN (%s)" % query_sub_in ) # print query_sql conn = cymysql.connect( host=Config.MYSQL_HOST, port=Config.MYSQL_PORT, user=Config.MYSQL_USER, passwd=Config.MYSQL_PASS, db=Config.MYSQL_DB, charset="utf8", ) cur = conn.cursor() cur.execute(query_sql) cur.close() conn.commit() conn.close()
def update_all_user(self, dt_transfer): import cymysql update_transfer = {} query_head = 'UPDATE user' query_sub_when = '' query_sub_when2 = '' query_sub_in = None alive_user_count = 0 bandwidth_thistime = 0 if get_config().MYSQL_SSL_ENABLE == 1: conn = cymysql.connect(host=get_config().MYSQL_HOST, port=get_config().MYSQL_PORT, user=get_config().MYSQL_USER, passwd=get_config().MYSQL_PASS, db=get_config().MYSQL_DB, charset='utf8',ssl={'ca':get_config().MYSQL_SSL_CA,'cert':get_config().MYSQL_SSL_CERT,'key':get_config().MYSQL_SSL_KEY}) else: conn = cymysql.connect(host=get_config().MYSQL_HOST, port=get_config().MYSQL_PORT, user=get_config().MYSQL_USER, passwd=get_config().MYSQL_PASS, db=get_config().MYSQL_DB, charset='utf8') conn.autocommit(True) for id in dt_transfer.keys(): if dt_transfer[id][0] == 0 and dt_transfer[id][1] == 0: continue query_sub_when += ' WHEN %s THEN u+%s' % (id, dt_transfer[id][0] * self.traffic_rate) query_sub_when2 += ' WHEN %s THEN d+%s' % (id, dt_transfer[id][1] * self.traffic_rate) update_transfer[id] = dt_transfer[id] alive_user_count = alive_user_count + 1 cur = conn.cursor() cur.execute("INSERT INTO `user_traffic_log` (`id`, `user_id`, `u`, `d`, `Node_ID`, `rate`, `traffic`, `log_time`) VALUES (NULL, '" + str(self.port_uid_table[id]) + "', '" + str(dt_transfer[id][0]) +"', '" + str(dt_transfer[id][1]) + "', '" + str(get_config().NODE_ID) + "', '" + str(self.traffic_rate) + "', '" + self.trafficShow((dt_transfer[id][0]+dt_transfer[id][1]) * self.traffic_rate) + "', unix_timestamp()); ") cur.close() bandwidth_thistime = bandwidth_thistime + ((dt_transfer[id][0] + dt_transfer[id][1]) * self.traffic_rate) if query_sub_in is not None: query_sub_in += ',%s' % id else: query_sub_in = '%s' % id if query_sub_when != '': query_sql = query_head + ' SET u = CASE port' + query_sub_when + \ ' END, d = CASE port' + query_sub_when2 + \ ' END, t = unix_timestamp() ' + \ ' WHERE port IN (%s)' % query_sub_in cur = conn.cursor() cur.execute(query_sql) cur.close() cur = conn.cursor() cur.execute("UPDATE `ss_node` SET `node_heartbeat`=unix_timestamp(),`node_bandwidth`=`node_bandwidth`+'" + str(bandwidth_thistime) + "' WHERE `id` = " + str(get_config().NODE_ID) + " ; ") cur.close() cur = conn.cursor() cur.execute("INSERT INTO `ss_node_online_log` (`id`, `node_id`, `online_user`, `log_time`) VALUES (NULL, '" + str(get_config().NODE_ID) + "', '" + str(alive_user_count) + "', unix_timestamp()); ") cur.close() cur = conn.cursor() cur.execute("INSERT INTO `ss_node_info` (`id`, `node_id`, `uptime`, `load`, `log_time`) VALUES (NULL, '" + str(get_config().NODE_ID) + "', '" + str(self.uptime()) + "', '" + str(self.load()) + "', unix_timestamp()); ") cur.close() online_iplist = ServerPool.get_instance().get_servers_iplist() for id in online_iplist.keys(): for ip in online_iplist[id]: cur = conn.cursor() cur.execute("INSERT INTO `alive_ip` (`id`, `nodeid`,`userid`, `ip`, `datetime`) VALUES (NULL, '" + str(get_config().NODE_ID) + "','" + str(self.port_uid_table[id]) + "', '" + str(ip) + "', unix_timestamp())") cur.close() detect_log_list = ServerPool.get_instance().get_servers_detect_log() for port in detect_log_list.keys(): for rule_id in detect_log_list[port]: cur = conn.cursor() cur.execute("INSERT INTO `detect_log` (`id`, `user_id`, `list_id`, `datetime`, `node_id`) VALUES (NULL, '" + str(self.port_uid_table[port]) + "', '" + str(rule_id) + "', UNIX_TIMESTAMP(), '" + str(get_config().NODE_ID) + "')") cur.close() deny_str = "" if platform.system() == 'Linux' and get_config().ANTISSATTACK == 1 : wrong_iplist = ServerPool.get_instance().get_servers_wrong() server_ip = socket.gethostbyname(get_config().MYSQL_HOST) for id in wrong_iplist.keys(): for ip in wrong_iplist[id]: realip = "" is_ipv6 = False if common.is_ip(ip) != False: if(common.is_ip(ip) == socket.AF_INET): realip = ip else: if common.match_ipv4_address(ip) != None: realip = common.match_ipv4_address(ip) else: is_ipv6 = True realip = ip else: continue if str(realip) == str(server_ip): continue cur = conn.cursor() cur.execute("SELECT * FROM `blockip` where `ip` = '" + str(realip) + "'") rows = cur.fetchone() cur.close() if rows != None: continue if get_config().CLOUDSAFE == 1: cur = conn.cursor() cur.execute("INSERT INTO `blockip` (`id`, `nodeid`, `ip`, `datetime`) VALUES (NULL, '" + str(get_config().NODE_ID) + "', '" + str(realip) + "', unix_timestamp())") cur.close() else: if is_ipv6 == False: os.system('route add -host %s gw 127.0.0.1' % str(realip)) deny_str = deny_str + "\nALL: " + str(realip) else: os.system('ip -6 route add ::1/128 via %s/128' % str(realip)) deny_str = deny_str + "\nALL: [" + str(realip) +"]/128" logging.info("Local Block ip:" + str(realip)) if get_config().CLOUDSAFE == 0: deny_file=open('/etc/hosts.deny','a') fcntl.flock(deny_file.fileno(),fcntl.LOCK_EX) deny_file.write(deny_str + "\n") deny_file.close() conn.close() return update_transfer
def del_server_out_of_bound_safe(rows): #停止超流量的服务 #启动没超流量的服务 #修改下面的逻辑要小心包含跨线程访问 for row in rows: if ServerPool.get_instance().server_is_run(row[0]) is True: if Config.SERVER_TYPE=='SIGN' and row[7] in [0]: #状态为0时关闭服务 if row[5] == 0 or row[6] == 0: #stop disable or switch off user logging.info('db stop server at port [%s] reason: disable' % (row[0])) ServerPool.get_instance().del_server(row[0]) if row[11]<=time.time() or row[12]+row[13]>=row[14]: #stop disable or switch off user logging.info('db stop server at port [%s] reason: disable' % (row[0])) ServerPool.get_instance().del_server(row[0]) else : #状态为0时关闭服务 if row[5] == 0 or row[6] == 0: #stop disable or switch off user logging.info('db stop server at port [%s] reason: disable' % (row[0])) ServerPool.get_instance().del_server(row[0]) #包月限流超额停止服务 elif row[10] + row[9] >= row[8] and (row[7] in [1]): #stop out bandwidth user logging.info('db stop server at port [%s] reason: out bandwidth' % (row[0])) ServerPool.get_instance().del_server(row[0]) # elif (row[7] in [2,1]) and time.time() > row[8]*24*60*60+row[9]: # logging.info('db stop server at port [%s] reason: Service maturity' % (row[0])) # ServerPool.get_instance().del_server(row[0]) #修改密码停止服务 if ServerPool.get_instance().tcp_servers_pool[row[0]]._config['password'] != row[4]: #password changed logging.info('db stop server at port [%s] reason: password changed' % (row[0])) ServerPool.get_instance().del_server(row[0]) #如果当前节点是VIP且当前用户没有充值过则停止服务 if Config.SERVER_TYPE=='VIP' and row[7] == 0: if not (row[15]>time.time() and row[12]+row[13]<row[14]): ServerPool.get_instance().del_server(row[0]) else: if row[5] == 1 and row[6] == 1 : if Config.SERVER_TYPE=='FREE': #固定流量 if (row[7] in [0,3]) and row[1] + row[2] < row[3]: logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4]) # #包月限流流量 if row[7] == 1 and row[10] + row[9] < row[8]: logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4]) #包月不限流量 if row[7]==2 : logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4]) if Config.SERVER_TYPE=='VIP': #固定流量 if row[7] == 1 and row[10] + row[9] < row[8]: logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4]) #包月限流流量 if row[7]==2 : logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4]) #包月不限流量 if row[7]==3 and row[1] + row[2] < row[3]: logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4]) #付费签到 if row[15]>time.time() and row[12]+row[13]<row[14]: logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4]) if Config.SERVER_TYPE=='SIGN': if row[11]>time.time() and row[12]+row[13]<row[14]: logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4]) if row[7] == 1 and row[10] + row[9] < row[8]: logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4]) #包月限流流量 if row[7]==2 : logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4]) #包月不限流量 if row[7]==3 and row[1] + row[2] < row[3]: logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4])
def del_server_out_of_bound_safe(last_rows, rows): #停止超流量的服务 #启动没超流量的服务 #需要动态载入switchrule,以便实时修改规则 try: import switchrule reload(switchrule) except Exception as e: logging.error('load switchrule.py fail') cur_servers = {} for row in rows: try: allow = switchrule.isTurnOn(row) and row['enable'] == 1 and row['u'] + row['d'] < row['transfer_enable'] except Exception as e: allow = False port = row['port'] passwd = row['passwd'] cur_servers[port] = passwd if ServerPool.get_instance().server_is_run(port) > 0: if not allow: logging.info('db stop server at port [%s]' % (port,)) ServerPool.get_instance().cb_del_server(port) elif (port in ServerPool.get_instance().tcp_servers_pool and ServerPool.get_instance().tcp_servers_pool[port]._config['password'] != passwd) \ or (port in ServerPool.get_instance().tcp_ipv6_servers_pool and ServerPool.get_instance().tcp_ipv6_servers_pool[port]._config['password'] != passwd): #password changed logging.info('db stop server at port [%s] reason: password changed' % (port,)) ServerPool.get_instance().cb_del_server(port) ServerPool.get_instance().new_server(port, passwd) elif allow and ServerPool.get_instance().server_run_status(port) is False: logging.info('db start server at port [%s] pass [%s]' % (port, passwd)) ServerPool.get_instance().new_server(port, passwd) for row in last_rows: if row['port'] in cur_servers: pass else: logging.info('db stop server at port [%s] reason: port not exist' % (row['port'])) ServerPool.get_instance().cb_del_server(row['port'])
def update_all_user(self, dt_transfer): global webapi update_transfer = {} alive_user_count = 0 bandwidth_thistime = 0 data = [] for id in dt_transfer.keys(): if dt_transfer[id][0] == 0 and dt_transfer[id][1] == 0: continue data.append({ "u": dt_transfer[id][0], "d": dt_transfer[id][1], "user_id": self.port_uid_table[id], }) update_transfer[id] = dt_transfer[id] webapi.postApi("traffic", {"node_id": get_config().NODE_ID}, {"data": data}) webapi.postApi("uptimeinfo", {"node_id": get_config().NODE_ID}, {"node_id": get_config().NODE_ID}) online_iplist = ServerPool.get_instance().get_servers_iplist() data = [] for port in online_iplist.keys(): for ip in online_iplist[port]: data.append({"ip": ip, "user_id": self.port_uid_table[port]}) webapi.postApi("aliveip", {"node_id": get_config().NODE_ID}, {"data": data}) detect_log_list = ServerPool.get_instance().get_servers_detect_log() data = [] for port in detect_log_list.keys(): for rule_id in detect_log_list[port]: data.append({ "list_id": rule_id, "user_id": self.port_uid_table[port] }) webapi.postApi( "detectlog", {"node_id": get_config().NODE_ID}, {"data": data}, ) deny_str = "" data = [] if platform.system() == "Linux" and get_config().ANTISSATTACK == 1: wrong_iplist = ServerPool.get_instance().get_servers_wrong() server_ip = socket.gethostbyname(get_config().MYSQL_HOST) for id in wrong_iplist.keys(): for ip in wrong_iplist[id]: realip = "" is_ipv6 = False if common.is_ip(ip): if common.is_ip(ip) == socket.AF_INET: realip = ip else: if common.match_ipv4_address(ip) is not None: realip = common.match_ipv4_address(ip) else: is_ipv6 = True realip = ip else: continue if str(realip).find(str(server_ip)) != -1: continue has_match_node = False for node_ip in self.node_ip_list: if str(realip).find(node_ip) != -1: has_match_node = True continue if has_match_node: continue if get_config().CLOUDSAFE == 1: data.append({"ip": realip}) else: if not is_ipv6: os.system("route add -host %s gw 127.0.0.1" % str(realip)) deny_str = deny_str + "\nALL: " + str(realip) else: os.system("ip -6 route add ::1/128 via %s/128" % str(realip)) deny_str = deny_str + "\nALL: [" + str( realip) + "]/128" logging.info("Local Block ip:" + str(realip)) if get_config().CLOUDSAFE == 0: deny_file = open("/etc/hosts.deny", "a") fcntl.flock(deny_file.fileno(), fcntl.LOCK_EX) deny_file.write(deny_str) deny_file.close() webapi.postApi( "block_ip", {"node_id": get_config().NODE_ID}, {"data": data}, ) return update_transfer
break port = int(request.args['port'][0]) if ServerPool.get_instance().del_server(port) is True: retcode = 0 retmsg = 'success' except Exception, e: retmsg = str(e) finally: break elif request.uri.startswith('/cmd/new_server'): while True: try: if not 'key' in request.args or Config.REST_APIKEY != request.args['key'][0]: retmsg = 'key error' break port = int(request.args['port'][0]) passwd = request.args['passwd'][0] ret = ServerPool.get_instance().new_server(port, passwd) if ret is True: retcode = 0 retmsg = 'success' else: retmsg = ret except Exception, e: retmsg = str(e) finally: break return json.dumps({'code': retcode, 'msg': retmsg})
def push_db_all_user(self): #更新用户流量到数据库 last_transfer = self.last_get_transfer curr_transfer = ServerPool.get_instance().get_servers_transfer() #上次和本次的增量 dt_transfer = {} for id in curr_transfer.keys(): if id in last_transfer: if last_transfer[id][0] == curr_transfer[id][0] and last_transfer[id][1] == curr_transfer[id][1]: continue elif curr_transfer[id][0] == 0 and curr_transfer[id][1] == 0: continue elif last_transfer[id][0] <= curr_transfer[id][0] and \ last_transfer[id][1] <= curr_transfer[id][1]: dt_transfer[id] = [curr_transfer[id][0] - last_transfer[id][0], curr_transfer[id][1] - last_transfer[id][1]] else: dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] else: if curr_transfer[id][0] == 0 and curr_transfer[id][1] == 0: continue dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] self.last_get_transfer = curr_transfer query_head = 'UPDATE user' query_sub_when = '' query_sub_when2 = '' query_sub_in = None last_time = time.time() for id in dt_transfer.keys(): query_sub_when += ' WHEN %s THEN u+%s' % (id, dt_transfer[id][0]) query_sub_when2 += ' WHEN %s THEN d+%s' % (id, dt_transfer[id][1]) if query_sub_in is not None: query_sub_in += ',%s' % id else: query_sub_in = '%s' % id if query_sub_when == '': return #CASE WHEN THEN END 语句 #遇到port(端口)是id(端口id)就u(上行流量)增加 结束,d(下行流量)增加 结束,t(最后连接时间)更新,在端口为[所有端口]的地方 query_sql = query_head + ' SET u = CASE port' + query_sub_when + \ ' END, d = CASE port' + query_sub_when2 + \ ' END, t = ' + str(int(last_time)) + \ ' WHERE port IN (%s)' % query_sub_in #print query_sql conn = cymysql.connect(host=Config.MYSQL_HOST, port=Config.MYSQL_PORT, user=Config.MYSQL_USER, passwd=Config.MYSQL_PASS, db=Config.MYSQL_DB, charset='utf8') mealNode = conn.cursor() mealNode.execute("SELECT mid FROM meal_node WHERE nodeMark = '%s'" % (Config.SERVER_MARK)) mealNodeRows = [] mealNodes = None for a in mealNode.fetchall(): b = list(a) if mealNodes is not None: mealNodes += ',%s' % b[0] else: mealNodes = '%s' % b[0] #print mealNodes mealNode.close() query_sql += 'AND mid in (%s)' % (mealNodes) cur = conn.cursor() cur.execute(query_sql) cur.close() conn.commit() conn.close()
def del_server_out_of_bound_safe(rows): #停止超流量的服务 #启动没超流量的服务 #修改下面的逻辑要小心包含跨线程访问 global email_list for row in rows: # 收集需要发送邮件的用户id if ServerPool.get_instance().server_is_run(row[0]) is True: if row[5] == 0 or row[6] == 0: #stop disable or switch off user logging.info('db stop server at port [%s] reason: disable' % (row[0])) ServerPool.get_instance().del_server(row[0]) elif row[1] + row[2] >= row[3]: #stop out bandwidth user email_list.append(row[9]) logging.info('db stop server at port [%s] reason: out bandwidth' % (row[0])) ServerPool.get_instance().del_server(row[0]) if row[8] != "" and row[8] < datetime.datetime.now(): #stop out bandwidth user email_list.append(row[9]) logging.info('db stop server at port [%s] reason: end_date < %s' % (row[0], datetime.datetime.now())) ServerPool.get_instance().del_server(row[0]) if ServerPool.get_instance().tcp_servers_pool[row[0]]._config['password'] != row[4]: #password changed logging.info('db stop server at port [%s] reason: password changed' % (row[0])) ServerPool.get_instance().del_server(row[0]) else: if row[5] == 1 and row[6] == 1 and row[1] + row[2] < row[3] and row[8] != "" and row[8] > datetime.datetime.now(): logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4]) else: email_list.append(row[9])
def del_server_out_of_bound_safe(self, last_rows, rows): #停止超流量的服务 #启动没超流量的服务 try: switchrule = importloader.load('switchrule') except Exception as e: logging.error('load switchrule.py fail') cur_servers = {} new_servers = {} allow_users = {} mu_servers = {} config = shell.get_config(False) for row in rows: try: allow = switchrule.isTurnOn(row) and row['enable'] == 1 and row['u'] + row['d'] < row['transfer_enable'] except Exception as e: allow = False port = row['port'] passwd = common.to_bytes(row['passwd']) if hasattr(passwd, 'encode'): passwd = passwd.encode('utf-8') cfg = {'password': passwd} if 'id' in row: self.port_uid_table[row['port']] = row['id'] read_config_keys = ['method', 'obfs', 'obfs_param', 'protocol', 'protocol_param', 'forbidden_ip', 'forbidden_port', 'speed_limit_per_con', 'speed_limit_per_user'] for name in read_config_keys: if name in row and row[name]: cfg[name] = row[name] merge_config_keys = ['password'] + read_config_keys for name in cfg.keys(): if hasattr(cfg[name], 'encode'): try: cfg[name] = cfg[name].encode('utf-8') except Exception as e: logging.warning('encode cfg key "%s" fail, val "%s"' % (name, cfg[name])) if port not in cur_servers: cur_servers[port] = passwd else: logging.error('more than one user use the same port [%s]' % (port,)) continue if 'protocol' in cfg and 'protocol_param' in cfg and common.to_str(cfg['protocol']) in obfs.mu_protocol(): if '#' in common.to_str(cfg['protocol_param']): mu_servers[port] = passwd allow = True if allow: if port not in mu_servers: allow_users[port] = cfg cfgchange = False if port in ServerPool.get_instance().tcp_servers_pool: relay = ServerPool.get_instance().tcp_servers_pool[port] for name in merge_config_keys: if name in cfg and not self.cmp(cfg[name], relay._config[name]): cfgchange = True break if not cfgchange and port in ServerPool.get_instance().tcp_ipv6_servers_pool: relay = ServerPool.get_instance().tcp_ipv6_servers_pool[port] for name in merge_config_keys: if (name in cfg) and ((name not in relay._config) or not self.cmp(cfg[name], relay._config[name])): cfgchange = True break if port in mu_servers: if ServerPool.get_instance().server_is_run(port) > 0: if cfgchange: logging.info('db stop server at port [%s] reason: config changed: %s' % (port, cfg)) ServerPool.get_instance().cb_del_server(port) self.force_update_transfer.add(port) new_servers[port] = (passwd, cfg) else: self.new_server(port, passwd, cfg) else: if ServerPool.get_instance().server_is_run(port) > 0: if config['additional_ports_only'] or not allow: logging.info('db stop server at port [%s]' % (port,)) ServerPool.get_instance().cb_del_server(port) self.force_update_transfer.add(port) else: if cfgchange: logging.info('db stop server at port [%s] reason: config changed: %s' % (port, cfg)) ServerPool.get_instance().cb_del_server(port) self.force_update_transfer.add(port) new_servers[port] = (passwd, cfg) elif not config['additional_ports_only'] and allow and port > 0 and port < 65536 and ServerPool.get_instance().server_run_status(port) is False: self.new_server(port, passwd, cfg) for row in last_rows: if row['port'] in cur_servers: pass else: logging.info('db stop server at port [%s] reason: port not exist' % (row['port'])) ServerPool.get_instance().cb_del_server(row['port']) self.clear_cache(row['port']) if row['port'] in self.port_uid_table: del self.port_uid_table[row['port']] if len(new_servers) > 0: from shadowsocks import eventloop self.event.wait(eventloop.TIMEOUT_PRECISION + eventloop.TIMEOUT_PRECISION / 2) for port in new_servers.keys(): passwd, cfg = new_servers[port] self.new_server(port, passwd, cfg) logging.debug('db allow users %s \nmu_servers %s' % (allow_users, mu_servers)) for port in mu_servers: ServerPool.get_instance().update_mu_users(port, allow_users) self.mu_ports = mu_servers
def del_server_out_of_bound_safe(self, last_rows, rows): #停止超流量的服务 #启动没超流量的服务 keymap = {} try: switchrule = importloader.load('switchrule') keymap = switchrule.getRowMap() except Exception as e: logging.error('load switchrule.py fail') cur_servers = {} new_servers = {} allow_users = {} mu_servers = {} config = shell.get_config(False) for row in rows: try: allow = switchrule.isTurnOn(row) and row['enable'] == 1 and row['u'] + row['d'] < row['transfer_enable'] except Exception as e: allow = False port = row['port'] passwd = common.to_bytes(row['passwd']) if hasattr(passwd, 'encode'): passwd = passwd.encode('utf-8') cfg = {'password': passwd} if 'id' in row: self.port_uid_table[row['port']] = row['id'] read_config_keys = ['method', 'obfs', 'obfs_param', 'protocol', 'protocol_param', 'forbidden_ip', 'forbidden_port', 'speed_limit_per_con', 'speed_limit_per_user'] for name in read_config_keys: if name in row and row[name]: if name in keymap: cfg[keymap[name]] = row[name] else: cfg[name] = row[name] merge_config_keys = ['password'] + read_config_keys for name in cfg.keys(): if hasattr(cfg[name], 'encode'): try: cfg[name] = cfg[name].encode('utf-8') except Exception as e: logging.warning('encode cfg key "%s" fail, val "%s"' % (name, cfg[name])) if port not in cur_servers: cur_servers[port] = passwd else: logging.error('more than one user use the same port [%s]' % (port,)) continue if 'protocol' in cfg and 'protocol_param' in cfg and common.to_str(cfg['protocol']) in obfs.mu_protocol(): if '#' in common.to_str(cfg['protocol_param']): mu_servers[port] = passwd allow = True if allow: if port not in mu_servers: allow_users[port] = cfg cfgchange = False if port in ServerPool.get_instance().tcp_servers_pool: relay = ServerPool.get_instance().tcp_servers_pool[port] for name in merge_config_keys: if name in cfg and not self.cmp(cfg[name], relay._config[name]): cfgchange = True break if not cfgchange and port in ServerPool.get_instance().tcp_ipv6_servers_pool: relay = ServerPool.get_instance().tcp_ipv6_servers_pool[port] for name in merge_config_keys: if (name in cfg) and ((name not in relay._config) or not self.cmp(cfg[name], relay._config[name])): cfgchange = True break if port in mu_servers: if ServerPool.get_instance().server_is_run(port) > 0: if cfgchange: logging.info('db stop server at port [%s] reason: config changed: %s' % (port, cfg)) ServerPool.get_instance().cb_del_server(port) self.force_update_transfer.add(port) new_servers[port] = (passwd, cfg) else: self.new_server(port, passwd, cfg) else: if ServerPool.get_instance().server_is_run(port) > 0: if config['additional_ports_only'] or not allow: logging.info('db stop server at port [%s]' % (port,)) ServerPool.get_instance().cb_del_server(port) self.force_update_transfer.add(port) else: if cfgchange: logging.info('db stop server at port [%s] reason: config changed: %s' % (port, cfg)) ServerPool.get_instance().cb_del_server(port) self.force_update_transfer.add(port) new_servers[port] = (passwd, cfg) elif not config['additional_ports_only'] and allow and port > 0 and port < 65536 and ServerPool.get_instance().server_run_status(port) is False: self.new_server(port, passwd, cfg) for row in last_rows: if row['port'] in cur_servers: pass else: logging.info('db stop server at port [%s] reason: port not exist' % (row['port'])) ServerPool.get_instance().cb_del_server(row['port']) self.clear_cache(row['port']) if row['port'] in self.port_uid_table: del self.port_uid_table[row['port']] if len(new_servers) > 0: from shadowsocks import eventloop self.event.wait(eventloop.TIMEOUT_PRECISION + eventloop.TIMEOUT_PRECISION / 2) for port in new_servers.keys(): passwd, cfg = new_servers[port] self.new_server(port, passwd, cfg) logging.debug('db allow users %s \nmu_servers %s' % (allow_users, mu_servers)) for port in mu_servers: ServerPool.get_instance().update_mu_users(port, allow_users) self.mu_ports = mu_servers
def del_server_out_of_bound_safe(rows): #停止超流量的服务 #启动没超流量的服务 #修改下面的逻辑要小心包含跨线程访问 for row in rows: ##[port=0, u=1, d=2, transfer_enable=3, sspassword=4, switch=5, enable=6,type=7,overdue=8] ##端口,使用流量1,使用流量2,总流量3,端口密码4,是否打开5,是否可用6,套餐性质A.B7,过期时间8 if ServerPool.get_instance().server_is_run(row[0]) is True: if row[5] == 0 or row[6] == 0: #stop disable or switch off user logging.info('db stop server at port [%s] reason: disable' % (row[0])) ServerPool.get_instance().del_server(row[0]) elif row[7] == 'A' and row[1] + row[2] >= row[3]: #stop out bandwidth user logging.info('db stop server at port [%s] reason: out bandwidth' % (row[0])) ServerPool.get_instance().del_server(row[0]) DbTransfer.get_instance().changeStatus(-1,row[0]) elif row[7] == 'B' and time.time() >= row[8]: #stop overdue user logging.info('db stop server at port [%s] reason: be overdue' % (row[0])) ServerPool.get_instance().del_server(row[0]) DbTransfer.get_instance().changeStatus(-2,row[0]) if ServerPool.get_instance().tcp_servers_pool[row[0]]._config['password'] != row[4]: #password changed logging.info('db stop server at port [%s] reason: password changed' % (row[0])) ServerPool.get_instance().del_server(row[0]) else: if row[5] == 1 and row[6] == 1 and row[7] == 'A' and row[1] + row[2] < row[3]: logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4]) elif row[5] == 1 and row[6] == 1 and row[7] == 'B' and time.time() < row[8]: logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4])