diff --git a/o_manager.py b/o_manager.py index 217194a..2748ba0 100644 --- a/o_manager.py +++ b/o_manager.py @@ -42,9 +42,18 @@ class OManager: if not name: name = f"openvpn-{self.new_idx}" os.system(f"groupadd vpn{self.new_idx}") - op = Openvpn(cfg_fp, self.new_idx, folder_path, - f"{self.base_port + self.new_idx}", "script.sh.template", "3proxy.cfg.template", name=name, - additional_cfg=additional_cfg) + ovpn_config = { + "cfg_fp": cfg_fp, + "name": name, + "additional_cfg": additional_cfg, + } + env_config = { + "folder_path": folder_path, + "script_template_fp": "script.sh.template", + "proxycfg_template_fp": "3proxy.cfg.template", + } + op = Openvpn(self.new_idx, ovpn_config=ovpn_config, + env_config=env_config) self.instances.append({ "op": op, "idx": self.new_idx, @@ -168,10 +177,12 @@ class OManager: self.keep_applying_weights())) def calc_weights(self): - n_up = 5 - n_down = 2 + # n_up = 5 + # n_down = 2 weights = [] for i in self.instances: + n_up = i["op"].n_up + n_down = i["op"].n_down ping_stat = i["op"].get_ping_stat(lines=max(n_up, n_down)) ping_stat = [i.split(",")[-1] != "-1" for i in ping_stat] #print("ping status:", ping_stat) diff --git a/openvpn.py b/openvpn.py index 9d25186..094e0b2 100644 --- a/openvpn.py +++ b/openvpn.py @@ -43,38 +43,63 @@ RUNNING = "running" class Openvpn: - def __init__(self, cfg_fp, idx, folder_path, management_port, template_fp, proxycfg_template_fp, name=None, additional_cfg={}, loop=None): - self.cfg_fp = cfg_fp + """ + ovpn_config:{ + cfg_fp: file path of ovpn configuration + name: name of this openvpn instance + additional_cfg: additional changes to be made to the existing ovpn file, usually as a way to feed in auth details + enabled: whether this instance should be started right away, default: False + ping_timeout: ping timeout for quality detection, unit is ms, default: 100 + n_up: number of consecutive successful pings to bring connection status up, default: 5 + n_down: number of consecutive failed pings to bring connection status down, default: 2 + } + env_config:{ + folder_path: path of the session folder + script_template_fp: file path of script template + proxycfg_template_fp: filepath of 3proxy config + } + """ + + def __init__(self, idx, ovpn_config, env_config, loop=None): self.idx = idx self.interface = f"tun{idx}" - self.folder_path = folder_path - self.management_port = management_port self.pids = [] self.status = IDLE self.proc = None self.exit_future = None - self.additional_cfg = additional_cfg self.run_task = [] - # self.openvpn_api = None - self.name = name self.pid_fp = None - # TODO: update paths function - self.io_stat_fp = os.path.join(self.folder_path, "io_stat.txt") - self.ping_stat_fp = os.path.join(self.folder_path, "ping_stat.txt") - self.template_fp = template_fp - self.proxycfg_template_fp = proxycfg_template_fp if loop: self.loop = loop else: self.loop = asyncio.get_event_loop() + self.load_cfg(ovpn_config, env_config) - def load_cfg(self): - pass + def load_cfg(self, ovpn_config, env_config): + self.cfg_fp = ovpn_config["cfg_fp"] + self.name = ovpn_config["name"] + self.additional_cfg = ovpn_config.get("additional_cfg", {}) + self.ping_timeout = int(ovpn_config.get("ping_timeout", 100)) + self.n_up = int(ovpn_config.get("n_up", 5)) + self.n_down = int(ovpn_config.get("n_down"), 2) + assert self.ping_timeout > 0, "invalid ping_timeout value" + assert self.n_up >= 0 and self.n_down >= 0, "invalid n_up or n_down value" + + self.folder_path = env_config["folder_path"] + self.script_template_fp = env_config["script_template_fp"] + self.proxycfg_template_fp = env_config["proxycfg_template_fp"] + + self.io_stat_fp = os.path.join(self.folder_path, "io_stat.txt") + self.ping_stat_fp = os.path.join(self.folder_path, "ping_stat.txt") + + enabled = ovpn_config.get("enabled", False) + if enabled: + self.start() def generate_script(self): self.script_fp = os.path.join(self.folder_path, "script.sh") - with open(self.template_fp, "r") as template_f: + with open(self.script_template_fp, "r") as template_f: buf = template_f.read() template = Template(buf) script_log_fp = os.path.join(self.folder_path, "script_log.txt") @@ -230,9 +255,9 @@ class Openvpn: io_count = io_count[self.interface] open(self.io_stat_fp, "a").write( f"{datetime.utcnow().timestamp()},{io_count.bytes_recv},{io_count.bytes_sent}\n") - #command = ["ping", "-w", "1", "-c", "1", "8.8.8.8"] - command = ["fping", "-C", "1", "-t200", - "-I", self.interface, "-q", "8.8.8.8"] + # command = ["ping", "-w", "1", "-c", "1", "8.8.8.8"] + command = ["fping", "-C", "1", f"-t{self.ping_timeout}", + "-I", self.interface, "-q", "8.8.8.8"] # TODO: configurable ping host p = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) result = p.communicate() @@ -244,7 +269,7 @@ class Openvpn: f"{datetime.utcnow().timestamp()},{result}\n") async def monitor_task(self): - #print("running monitor task") + # print("running monitor task") while self.status == RUNNING: try: self.monitor_action() @@ -253,9 +278,9 @@ class Openvpn: await asyncio.sleep(5) async def run_cmd(self, cmd, group): - #print(f"run: {cmd}") + # print(f"run: {cmd}") while self.status == RUNNING: - #print("create proc") + # print("create proc") print(self.status) pid_fp = os.path.join(self.folder_path, f"{cmd[0]}_pid.txt") try: @@ -294,11 +319,3 @@ class Openvpn: if PID in self.pids: self.pids.remove(PID) await asyncio.sleep(5*60) - - -if __name__ == "__main__": - folder_fp = "/home/mantao/Desktop/t/" - cfg_fp = "/home/mantao/Desktop/t/TCP_Files/UK2-TCP.ovpn" - o1 = Openvpn(cfg_fp, 0, folder_fp, 8001, "script.sh.template", "3proxy.cfg", additional_cfg={ - "auth-user-pass": "/home/mantao/Desktop/t/fast.txt"}) - # o1.start()