diff --git a/src/adapters/DNSCryptproxy.py b/src/adapters/DNSCryptproxy.py new file mode 100755 index 0000000..104c9ff --- /dev/null +++ b/src/adapters/DNSCryptproxy.py @@ -0,0 +1,86 @@ +import subprocess +from typedef.konstants import Arch, ConfParams +from os import chdir, path +import platform +import multiprocessing +from multiprocessing import Process +from time import sleep + +class HandleDNSCryptProxy(): + lh = "127.0.0.1" + lhv6 = "::1" + cf = "1.1.1.1" + cfv6 = "2606:4700:4700::1111" + dnscrypt_pid = 0 + dnscryptcmd = None + + def __init__(self, default: str = "1.1.1.1", defaultv6: str = "2606:4700:4700::1111"): + self.default = default + self.defaultv6 = defaultv6 + pass + + def fork_dnscrypt(self): + dnscryptcmd = f"{self.dnscryptcmd}" + process = subprocess.Popen(dnscryptcmd, shell=True,close_fds=True) + print(f"DNSCryptProxy: {process.pid}") + self.dnscrypt_pid = process.pid + + # Be sure to run in thread or concurent.futures + def dnscrypt(self, state: bool = False): + chdir(ConfParams.BASEBINDIR) + dnscrypt_proxy_executable = path.join(ConfParams.BASEBINDIR, 'run_dnscrypt.sh') + pltfrm = platform.system() + if state == True: + if pltfrm == Arch.LINUX: + dnscrypt_start = dnscrypt_proxy_executable + " up" + print("Startin DNScrypt-proxy...", end=' ') + self.dnscryptcmd = f"pkexec sh -c '{dnscrypt_start}'" + multiprocessing.get_context('spawn') + fork = Process(target=self.fork_dnscrypt) + fork.run() + sleep(1.5) + + # TODO: OS/X + + + + + else: + if pltfrm == Arch.WINDOWS: + kill_dns_crypt = "change_dns.ps1" + if self.default != self.cf: + dns_bat = self.dns_ps1 % (self.default, self.defaultv6) + else: + dns_bat = self.dns_ps1 % (self.cf, self.cfv6) + with open(kill_dns_crypt, "w") as DNSFILE: + DNSFILE.write(f"{dns_bat}\n") + DNSFILE.write(f"{self.dnscrypt_stop}") + + + print(dns_bat) + print(self.dnscrypt_stop) + print("Killing dnscrypt-proxy.exe...") + self.dnscryptcmd = path.join(ConfParams.BASEBINDIR, "change_dns.ps1") + end_daemon_cmd = [ConfParams.GSUDO, "powershell.exe", self.dnscryptcmd] + proc2 = subprocess.Popen(end_daemon_cmd, shell=True) + proc2.wait(timeout=30) + proc_out,proc_err = proc2.communicate() + + #dnscmd = [ConfParams.GSUDO, path.join(ConfParams.BASEBINDIR, "change_dns.bat")] + #process = subprocess.Popen(dnscmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + self.dnscrypt_pid = 0 + + elif pltfrm == Arch.LINUX: + dnscrypt_start = dnscrypt_proxy_executable + " down" + print("Stopping DNScrypt-proxy...", end=' ') + self.dnscryptcmd = f"pkexec sh -c '{dnscrypt_start}'" + multiprocessing.get_context('spawn') + fork = Process(target=self.fork_dnscrypt) + fork.run() + sleep(1.5) + # TODO: OS/X + + chdir(ConfParams.KEYRINGDIR) + + + \ No newline at end of file diff --git a/src/kv/meile.kv b/src/kv/meile.kv index 59fa4cb..b5f3a25 100644 --- a/src/kv/meile.kv +++ b/src/kv/meile.kv @@ -65,6 +65,15 @@ WindowManager: size_hint_y: .6 size_hint_x: .6 pos_hint: {'x' : -.15, 'center_y' : .5} + ToolTipMDIconButton: + id: doh + opacity: 0 + tooltip_text: "DNS-over-HTTPS" + icon: "circle-slice-8" + theme_text_color: "Custom" + text_color: get_color_from_hex(MeileColors.INDICATOR) + on_release: root.menu_open() + pos_hint: {'x' : .90, 'center_y' : .5} ToolTipMDIconButton: id: settings_menu tooltip_text: "Menu" diff --git a/src/ui/screens.py b/src/ui/screens.py index fe1c5dc..1de8b60 100644 --- a/src/ui/screens.py +++ b/src/ui/screens.py @@ -16,6 +16,7 @@ from cli.v2ray import V2RayHandler from fiat.stripe_pay import scrtsxx from adapters.ChangeDNS import ChangeDNS +from adapters.DNSCryptproxy import HandleDNSCryptProxy as dcp from helpers.helpers import format_byte_size from helpers.bandwidth import compute_consumed_data, compute_consumed_hours, init_GetConsumedWhileConnected, GetConsumedWhileConnected @@ -379,6 +380,7 @@ class MainWindow(Screen): SubCaller = False PlanID = None + dnscrypt = False @@ -684,8 +686,38 @@ def menu_callback(self, selection): self.disconnect_from_node() sys.exit(0) + @delayable def start_dnscrypt(self): - pass + dnsproxy = dcp() + if not self.dnscrypt: + self.add_loading_popup("Starting DNSCryptProxy with user selected resolvers...") + yield 1.3 + t = Thread(target=lambda: dnsproxy.dnscrypt(state=True)) + t.start() + + while t.is_alive(): + print(".", end="") + yield 0.5 + + self.dnscrypt = True + self.remove_loading_widget(None) + self.display_dnscrypt_success(dnsproxy.dnscrypt_pid) + self.ids.doh.opacity = 1 + + else: + self.add_loading_popup("Terminating DNSCryptProxy...") + yield 1.3 + + t = Thread(target=lambda: dnsproxy.dnscrypt(state=False)) + t.start() + + while t.is_alive(): + print(".", end="") + yield 0.5 + + self.dnscrypt = False + self.remove_loading_widget(None) + self.ids.doh.opacity = 0 def build(self, dt): # Check to build Map @@ -868,6 +900,23 @@ def display_warp_success(self): ], ) self.dialog.open() + + @mainthread + def display_dnscrypt_success(self, pid): + + self.dialog = MDDialog( + text=f"You are now using DoH (DNS-over-HTTPS) and your DNS traffic is encrypted from prying eyes. {pid}", + md_bg_color=get_color_from_hex(MeileColors.BLACK), + buttons=[ + MDRaisedButton( + text="Okay", + theme_text_color="Custom", + text_color=MeileColors.BLACK, + on_release=self.remove_loading_widget + ), + ], + ) + self.dialog.open() @delayable def start_warp(self):