예제 #1
0
파일: tunnel.py 프로젝트: dunganau/qomui
    def run(self):
        ip = self.server_dict["ip"]
        firewall.allow_dest_ip(ip, "-I")

        self.log.emit(("info", "iptables: created rule for {}".format(ip)))

        try:
            if self.server_dict["tunnel"] == "WireGuard":
                self.wireguard()
            else:
                self.openvpn()
        except KeyError:
            self.openvpn()
예제 #2
0
    def openvpn(self):
        self.air_ssl_port = "1413"
        self.ws_ssl_port = "1194"
        path = "{}/temp.ovpn".format(ROOTDIR)
        cwd_ovpn = None
        provider = self.server_dict["provider"]
        ip = self.server_dict["ip"]

        try:
            port = self.server_dict["port"]
            protocol = self.server_dict["protocol"]

        except KeyError:
            pass

        if "bypass" in self.server_dict.keys():
            path = "{}/bypass.ovpn".format(ROOTDIR)
            time.sleep(2)

        else:
            path = "{}/temp.ovpn".format(ROOTDIR)

        if provider == "Airvpn":

            #create temp ssl config
            if protocol == "SSL":
                with open("{}/ssl_config".format(ROOTDIR), "r") as ssl_edit:
                    ssl_config = ssl_edit.readlines()
                    for line, value in enumerate(ssl_config):
                        if value.startswith("connect") is True:
                            ssl_config[line] = "connect = {}:{}\n".format(ip, port)
                        elif value.startswith("accept") is True:
                            ssl_config[line] = "accept = 127.0.0.1:{}\n".format(self.air_ssl_port)
                    ssl_config.append("verify = 3\n")
                    ssl_config.append("CAfile = /usr/share/qomui/Airvpn/stunnel.crt")
                    with open("{}/temp.ssl".format(ROOTDIR), "w") as ssl_dump:
                        ssl_dump.writelines(ssl_config)
                        ssl_dump.close()
                    ssl_edit.close()
                self.write_config(self.server_dict)
                self.ssl_thread = threading.Thread(target=self.ssl, args=(ip,))
                self.ssl_thread.start()
                self.log.emit(("info", "Started Stunnel process in new thread"))

            #create temp ssh config
            elif protocol == "SSH":
                self.write_config(self.server_dict)
                self.ssh_thread = threading.Thread(target=self.ssh, args=(ip,port,))
                self.ssh_thread.start()
                self.log.emit(("info", "Started SSH process in new thread"))
                time.sleep(2)
            else:
                self.write_config(self.server_dict)

        elif provider == "Mullvad":
            self.write_config(self.server_dict)

        elif provider == "PIA":
            self.write_config(self.server_dict)

        elif provider == "Windscribe":

            #create temp ssl config
            if protocol == "SSL":
                with open("{}/ssl_config".format(ROOTDIR), "r") as ssl_edit:
                    ssl_config = ssl_edit.readlines()
                    for line, value in enumerate(ssl_config):
                        if value.startswith("connect") is True:
                            ssl_config[line] = "connect = {}:{}\n".format(ip, port)
                        elif value.startswith("accept") is True:
                            ssl_config[line] = "accept = 127.0.0.1:{}\n".format(self.ws_ssl_port)
                    with open("{}/temp.ssl".format(ROOTDIR), "w") as ssl_dump:
                        ssl_dump.writelines(ssl_config)
                        ssl_dump.close()
                    ssl_edit.close()
                self.write_config(self.server_dict)
                self.ssl_thread = threading.Thread(target=self.ssl, args=(ip,))
                self.ssl_thread.start()
                self.log.emit(("info", "Started Stunnel process in new thread"))

            self.write_config(self.server_dict)

        elif provider == "ProtonVPN":
            self.write_config(self.server_dict)

        elif provider == "AzireVPN":
            self.write_config(self.server_dict)

        else:
            config_file = "{}/{}".format(ROOTDIR, self.server_dict["path"])

            try:
                edit = "{}/temp".format(provider)
                self.write_config(self.server_dict,
                                  edit=edit, path=config_file)

                path = "{}/{}/temp.ovpn".format(ROOTDIR, provider)

            except UnboundLocalError:
                path = config_file

            #setting cwd for OpenVPN is important if certifacte/key files separate from config file
            cwd_ovpn = os.path.dirname(config_file)

        if self.hop == "2":
            firewall.allow_dest_ip(self.hop_dict["ip"], "-I")

            if self.hop_dict["provider"] in SUPPORTED_PROVIDERS:
                hop_path = "{}/hop.ovpn".format(ROOTDIR)
                self.write_config(self.hop_dict, edit="hop")

            else:
                config_file = "{}/{}".format(ROOTDIR, self.hop_dict["path"])
                try:
                    edit = "{}/hop".format(self.hop_dict["provider"])
                    self.write_config(self.hop_dict, edit=edit, path=config_file)
                    hop_path = "{}/{}/temp.ovpn".format(ROOTDIR, self.hop_dict["provider"])

                except (UnboundLocalError, KeyError):
                    hop_path = config_file

                cwd_ovpn = os.path.dirname(config_file)
            self.hop_thread = threading.Thread(target=self.ovpn, args=(hop_path,
                                                                       "1", cwd_ovpn,))
            self.hop_thread.start()

            #wait until first hop is connected
            while self.connect_status == 0:
                time.sleep(1)

        self.ovpn(path, self.hop, cwd_ovpn)
예제 #3
0
    def ovpn(self, ovpn_file, h, cwd_ovpn):
        self.log.emit(("info", "Establishing new OpenVPN tunnel"))
        name = self.server_dict["name"]
        last_ip = self.server_dict["ip"]
        add = ""

        if "bypass" not in self.server_dict and h != 1:
             exe_custom_scripts("pre", self.server_dict["provider"], self.config)

        #if doublehop is selected additional arguments are needed for OpenVPN
        if h == "1":
            add = "_hop"
            name = self.hop_dict["name"]
            self.log.emit(("info", "Establishing connection to {} - first hop".format(name)))
            last_ip = self.hop_dict["ip"]
            cmd_ovpn = ['openvpn',
                        '--config', '{}'.format(ovpn_file),
                        '--route-nopull',
                        '--script-security', '2',
                        '--up', '{}/scripts/hop.sh -f {} {}'.format(
                                                                    ROOTDIR,
                                                                    self.hop_dict["ip"],
                                                                    self.server_dict["ip"]
                                                                     ),
                        '--down', '{}/scripts/hop_down.sh {}'.format(ROOTDIR, self.hop_dict["ip"])
                        ]

        elif h == "2":
            self.log.emit(("info", "Establishing connection to {} - second hop".format(name)))
            cmd_ovpn = ['openvpn',
                        '--config', '{}'.format(ovpn_file),
                        '--route-nopull',
                        '--script-security', '2',
                        '--up', '{}/hop.sh -s'.format(ROOTDIR)
                        ]

        else:
            self.log.emit(("info", "Establishing connection to {}".format(name)))
            cmd_ovpn = ['openvpn', '{}'.format(ovpn_file)]

        if "bypass" in self.server_dict:
            add = "_bypass"
            self.dns_bypass = self.config["alt_dns1"]
            self.dns_2_bypass = self.config["alt_dns2"]

        else:
            self.dns = self.config["alt_dns1"]
            self.dns_2 = self.config["alt_dns2"]

        ovpn_exe = Popen(cmd_ovpn, stdout=PIPE, stderr=STDOUT,
                         cwd=cwd_ovpn, bufsize=1, universal_newlines=True
                         )

        self.log.emit(("debug", "OpenVPN pid: {}".format(ovpn_exe.pid)))
        self.pid.emit((ovpn_exe.pid, "OpenVPN{}".format(add)))
        line = ovpn_exe.stdout.readline()
        self.status.emit("starting_timer{}".format(add))

        #keep this thread as long as openvpn process has not been terminated
        #disconnection from gui will kill the openvpn process and break the loop
        while line.find("SIGTERM[hard,] received, process exiting") == -1:
            time_measure = time.time()
            line_format = ("OpenVPN:" + line.replace('{}'.format(time.asctime()), '').replace('\n', ''))
            self.log.emit(("info", line_format))

            #signals that tunnel has been successfully established
            if line.find("Initialization Sequence Completed") != -1:
                if "bypass" not in self.server_dict and h != 1:
                     exe_custom_scripts("up", self.server_dict["provider"], self.config)
                self.connect_status = 1
                self.bypass.emit()
                self.status.emit("connection_established{}".format(add))
                self.log.emit(("info", "Successfully connected to {}".format(name)))

            elif line.find('TUN/TAP device') != -1:
                setattr(self, "tun{}".format(add), line_format.split(" ")[3])
                self.dev.emit(("tun{}".format(add), getattr(self, "tun{}".format(add))))

            #read dns servers pushed by OpenVPN server
            #if not found: fallback to alternatives ones from config file
            elif line.find('PUSH: Received control message:') != -1:
                dns_option_1 = line_format.find('dhcp-option')

                if dns_option_1 != -1 and self.config["alt_dns"] == 0:
                    option = line_format[dns_option_1:].split(",")[0]
                    setattr(self, "dns{}".format(add), option.split(" ")[2])
                    dns_option_2 = line_format.find('dhcp-option', dns_option_1+20)

                    if dns_option_2 != -1:
                        option = line_format[dns_option_2:].split(",")[0]
                        setattr(self, "dns_2{}".format(add), option.split(" ")[2])

                    else:
                        setattr(self, "dns_2{}".format(add), None)

                dns_manager.set_dns(getattr(self, "dns{}".format(add)), getattr(self, "dns_2{}".format(add)))
                self.dnsserver.emit((add, getattr(self, "dns{}".format(add)), getattr(self, "dns_2{}".format(add))))

            #might be redundant as gui checks for timeout anyway
            elif line.find("Restart pause, 10 second(s)") != -1:
                self.status.emit("conn_attempt_failed{}".format(add))
                self.log.emit(("info" ,"Connection attempt failed"))

            elif line.find('SIGTERM[soft,auth-failure]') != -1:
                self.status.emit("conn_attempt_failed{}".format(add))
                self.log.emit(("info", "Authentication error while trying to connect"))

            #bugfix for double-hop
            #sometimes whitelisting servers via iptables fails so we retry
            #need to investigate further
            elif line.find('write UDP: Operation not permitted') != -1:
                ips = []

                try:
                    hop_ip = self.hop_dict["ip"]
                    ips.append(hop_ip)

                except:
                    pass

                remote_ip = self.server_dict["ip"]
                ips.append(remote_ip)

                for ip in ips:
                    firewall.allow_dest_ip(ip, "-I")

            elif line.find("Exiting due to fatal error") != -1:
                self.status.emit("conn_attempt_failed{}".format(add))
                self.log.emit(("info", "Connection attempt failed due to fatal error"))

            #break if openvpn emits empty lines to avoid clogging log
            elif line == '':
                break

            line = ovpn_exe.stdout.readline()

        if "bypass" not in self.server_dict and h != 1:
             exe_custom_scripts("down", self.server_dict["provider"], self.config)
        self.log.emit(("info", "OpenVPN:" + line.replace('{}'.format(time.asctime()), '').replace('\n', '')))
        ovpn_exe.stdout.close()
        self.status.emit("tunnel_terminated{}".format(add))
        self.log.emit(("info", "OpenVPN - process killed"))

        #delete outbound rule for this server
        firewall.allow_dest_ip(last_ip, "-D")

        #reset bypass so it can work without second OpenVPN tunnel
        if add == "_bypass":
            setattr(self, "dns{}".format(add), self.config["alt_dns1"])
            setattr(self, "dns{}_2".format(add), self.config["alt_dns2"])
            setattr(self, "tun{}".format(add), None)
            self.dnsserver.emit((add, self.config["alt_dns1"], self.config["alt_dns2"]))
            self.dev.emit(("tun{}".format(add), getattr(self, "tun{}".format(add))))
            self.bypass.emit()

        else:
            setattr(self, "tun{}".format(add), None)
            self.dev.emit(("tun{}".format(add), getattr(self, "tun{}".format(add))))