├── README.md └── mirrorscript-v2.py /README.md: -------------------------------------------------------------------------------- 1 | # Mirrorscript-v2 2 | Script to change official Kali repository to mirrors. This helps increase packages update and downloading for some user. Please visit my blog [post](https://www.metahackers.pro/speed-kali-linux-update/). 3 | 4 | ## Requirements 5 | Kali Linux, 6 | Python3 7 | 8 | ## Usage 9 | Run the script in privilege mode, such that `sources.list` could be edited. 10 | 11 | ## Help 12 | ``` 13 | # python3 mirrorscript-v2.py -h 14 | usage: mirrorscript-v2.py [-h] [-v] [-https] [-src] 15 | 16 | Kali Mirrorscripts-v2 by IceM4nn automatically select the best kali mirror 17 | server and apply the configuration 18 | 19 | optional arguments: 20 | -h, --help show this help message and exit 21 | -v, --verbose enable verbose output 22 | -https use HTTPS in apt transport (default HTTP) 23 | -src enable sources packages (default disable) 24 | ``` 25 | 26 | ## Sample output: 27 | ``` 28 | # python3 mirrorscript-v2.py -v -https -src 29 | 30 | # 31 | # Mirrorscripts-v2 - By Hazmirul Afiq 32 | # Automatically select the best Kali mirror and apply the configuration 33 | # https://github.com/IceM4nn/mirrorscript-v2 34 | # https://www.metahackers.pro/speed-kali-linux-update/ 35 | # 36 | 37 | [-] Checking if 'apt-transport-https' package is installed. 38 | - apt-transport-https is installed 39 | 40 | [+] Getting mirror list ... 41 | [+] Found a lists of mirrors: 42 | - https://hlzmel.fsmg.org.nz/kali 43 | - https://wlglam.fsmg.org.nz/kali 44 | - https://mirror.karneval.cz/pub/linux/kali 45 | - https://ftp.acc.umu.se/mirror/kali.org/kali 46 | - https://mirrors.dotsrc.org/kali 47 | - https://ftp.halifax.rwth-aachen.de/kali 48 | - https://ftp2.nluug.nl/os/Linux/distr/kali 49 | - https://ftp1.nluug.nl/os/Linux/distr/kali 50 | - https://mirror.neostrada.nl/kali 51 | - https://kali.download/kali 52 | - https://mirrors.ocf.berkeley.edu/kali 53 | 54 | [+] Checking mirrors ... This could take some times. 55 | [+] Finding the best latency 56 | - hlzmel.fsmg.org.nz : 416.890 57 | - wlglam.fsmg.org.nz : 388.998 58 | - mirror.karneval.cz : 391.414 59 | - ftp.acc.umu.se : 313.722 60 | - mirrors.dotsrc.org : 314.235 61 | - ftp.halifax.rwth-aachen.de : 291.252 62 | - ftp2.nluug.nl : 297.838 63 | - ftp1.nluug.nl : 302.336 64 | - mirror.neostrada.nl : 294.256 65 | - kali.download : 40.478 66 | - mirrors.ocf.berkeley.edu : 348.848 67 | 68 | [+] Fastest mirror: ('kali.download', '040.478') 69 | [+] Preparing ... 70 | - Making a backup file /etc/apt/sources.list.bk ... 71 | - Checking sources.list for older entries ... 72 | - Commenting older entries ... 73 | - Done 74 | 75 | [+] Updating sources.list with new entry ... 76 | - Your new mirror: https://kali.download/kali 77 | 78 | [+] Done! 79 | - Run 'apt clean; apt update' for the changes to load. 80 | 81 | ``` -------------------------------------------------------------------------------- /mirrorscript-v2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # Mirrorscript v2 By Hazmirul Afiq 3 | import subprocess, requests, re, sys 4 | import operator 5 | import argparse, apt, os 6 | import threading 7 | from shutil import copyfile 8 | 9 | result_url = [] 10 | ping_result = [] 11 | mirrors = {} 12 | headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'} 13 | 14 | class fetch_thread(threading.Thread): 15 | def __init__(self, count, url,schema): 16 | threading.Thread.__init__(self) 17 | self.count = count + 1 18 | self.url = url 19 | self.schema = schema 20 | 21 | def run(self): 22 | try: 23 | response = requests.get(self.schema+self.url, headers=headers).status_code 24 | if response == 200: 25 | result_url.append(self.url) 26 | else: 27 | print("[!] " + self.url + " doesn't support " + self.schema) 28 | except Exception as e: 29 | print("[!] Failed to establish a connection to host " + self.schema + self.url) 30 | 31 | def fetch_url(urls,schema): 32 | threads = [] 33 | for count, url in enumerate(urls): 34 | count = fetch_thread(count, url,schema) 35 | threads.append(count) 36 | 37 | for i in threads: 38 | i.start() 39 | 40 | for i in threads: 41 | i.join() 42 | 43 | return result_url 44 | 45 | def ask(question,default): 46 | yes = set(['yes','y','ye']) 47 | no = set(['no','n']) 48 | yes.add('') if default == 'y' else no.add('') 49 | while True: 50 | choice = input(question + " Default [" + default + "]: ").lower() 51 | if choice in yes: 52 | return True 53 | elif choice in no: 54 | return False 55 | else: 56 | print("\t Please answer with [y] or [n]: "); 57 | 58 | class ping_thread(threading.Thread): 59 | def __init__(self, count, hostname): 60 | super(ping_thread, self).__init__() 61 | self.count = count + 1 62 | self.hostname = hostname 63 | 64 | def run(self): 65 | p = subprocess.Popen(['ping','-c 3', self.hostname], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() 66 | p = [str(x.decode('utf-8')) for x in p] 67 | 68 | if not p[0].strip(): 69 | # error 70 | print("\t[!] Error: Something went wrong ...") 71 | print("\t " + p[1].strip()) 72 | response = ask("\t Stuck at finding mirror latency. Do you want to retry[y] or skip[n]?",'n') 73 | if response: 74 | run(self.hostname) 75 | else: 76 | try: 77 | if "100% packet loss" in p[0].strip(): 78 | average = "[!] Unable to check " + self.hostname + " latency, potentially host block ICMP request." 79 | else: 80 | average = p[0].strip().splitlines()[-1].split('=')[1].split('/')[1] 81 | mirrors[self.hostname] = str(str(average).zfill(7)) 82 | except Exception as e: 83 | if not ask("\t[!] Something went wrong. would you like to try again [y] or [n].",'y'): 84 | print ("\t Exiting ...\n") 85 | sys.exit(1) 86 | if verbose: 87 | print("\t- {0:30} : {1}".format(self.hostname,average)) 88 | 89 | def ping_s(hostname): 90 | threads = [] 91 | for count, hostname in enumerate(hostname): 92 | count = ping_thread(count, hostname) 93 | threads.append(count) 94 | 95 | for i in threads: 96 | i.start() 97 | 98 | for i in threads: 99 | i.join() 100 | 101 | return ping_result 102 | 103 | 104 | if __name__ == "__main__": 105 | 106 | # Check if user is root first. 107 | if os.getuid() != 0: 108 | sys.exit("[!] Must run as root/sudo\n") 109 | 110 | # Argument parser 111 | parser = argparse.ArgumentParser(description='Kali Mirrorscripts-v2 by IceM4nn automatically select the best kali mirror server and apply the configuration') 112 | parser.add_argument('-v','--verbose', help='enable verbose output', action="store_true") 113 | parser.add_argument('-https', help='use HTTPS in apt transport (default HTTP)', action="store_true") 114 | parser.add_argument('-src', help='enable sources packages (default disable)', action="store_true") 115 | args = parser.parse_args() 116 | 117 | # Initialize arguments 118 | https = True if args.https else False 119 | verbose = True if args.verbose else False 120 | sources = True if args.src else False 121 | 122 | # Banner 123 | print("#") 124 | print("# Mirrorscripts-v2 - By Hazmirul Afiq") 125 | print("# Automatically select the best Kali mirror and apply the configuration") 126 | print("# https://github.com/IceM4nn/mirrorscript-v2") 127 | print("# https://www.metahackers.pro/speed-kali-linux-update/") 128 | print("#\n") 129 | 130 | if https: 131 | cache = apt.Cache() 132 | cache.open() 133 | 134 | package = "apt-transport-https" 135 | print("[-] Checking if '" + package + "' package is installed.") 136 | try: 137 | if cache[package].is_installed: 138 | if verbose: 139 | print("\t- "+package+" is installed\n") 140 | else: 141 | print("\t! "+package+" is NOT installed. Attempting to install ...") 142 | cache[package].mark_install() 143 | print("\t- Installing "+package+"\n") 144 | try: 145 | cache.commit() 146 | print("\n\t- "+package+" installed succesfully") 147 | except Exception as e: 148 | print("\t! package "+package+" is failing to install") 149 | print("\t "+str(e)) 150 | sys.exit(1) 151 | except KeyError as e: 152 | print("[!] The package \"" + package + "\" could not found in local apt cache. You may need to install it manually later after you've done update kali.") 153 | print(" For the time being, re-run the script without https support.") 154 | sys.exit(1) 155 | 156 | print("[+] Getting mirror list ...") 157 | response = requests.get('https://http.kali.org/README.mirrorlist', headers=headers).text 158 | urls = re.findall(r'(?:href="http(?:s|))(.*)(?:/README")',response)[2:] 159 | 160 | if verbose: 161 | print("[+] Found (" + str(len(urls)) + ") lists of mirrors:") 162 | for url in urls: 163 | print("\t- https" + url) 164 | print("") 165 | 166 | print("[+] Checking mirrors ...") 167 | schema = 'https' if https else 'http' 168 | new_urls = fetch_url(urls,schema) 169 | 170 | print("[+] Finding the best latency") 171 | 172 | hosts = [] 173 | for hostname in new_urls: 174 | hostname = hostname.split("//")[-1].split("/")[0].split('?')[0] 175 | hosts.append(hostname) 176 | 177 | # sending ping in threads 178 | ping_s(hosts) 179 | 180 | if verbose: 181 | print("") 182 | 183 | # sorted to fastest mirror 184 | sorted_mirrors = sorted(mirrors.items(), key=operator.itemgetter(1)) 185 | print("[+] Fastest mirror: " + str(sorted_mirrors[0])) 186 | 187 | print("[+] Preparing ...") 188 | 189 | # Making backup 190 | if verbose: 191 | print("\t- Making a backup file /etc/apt/sources.list.bk ...") 192 | 193 | copyfile('/etc/apt/sources.list', '/etc/apt/sources.list.bk') 194 | 195 | if verbose: 196 | print("\t- Checking sources.list for older entries ...") 197 | 198 | contents = [] 199 | file = open("/etc/apt/sources.list", "r+") 200 | if verbose: 201 | print("\t- Commenting older entries ...") 202 | i = 0 203 | for line in file.readlines(): 204 | if (re.search(r'^deb http(?:s|)://http\.kali\.org/kali', line, re.I)) or (re.search(r'^deb-src http(?:s|)://http\.kali\.org/kali', line, re.I)): 205 | newline = "#" + line 206 | file.write(newline) 207 | contents.append(newline) 208 | elif re.search(r'^# Autogenerated script by MirrorScripts-V2', line, re.I): 209 | print("\t! Found previous applies! Commenting it out ...") 210 | contents.append(line) 211 | i = 1 212 | elif i == 1: 213 | if not line.startswith("#"): 214 | newline = "#" + line 215 | file.write(newline) 216 | contents.append(newline) 217 | else: 218 | contents.append(line) 219 | i = i+1 220 | elif i == 2: 221 | if not line.startswith("#"): 222 | newline = "#" + line 223 | file.write(newline) 224 | contents.append(newline) 225 | else: 226 | contents.append(line) 227 | i = 0 228 | else: 229 | contents.append(line) 230 | file.seek(0) 231 | file.truncate() 232 | file.seek(0) 233 | for line in contents: 234 | file.write(line) 235 | file.close() 236 | if verbose: 237 | print("\t- Done\n") 238 | 239 | print("[+] Updating sources.list with new entry ...") 240 | 241 | matching = [s for s in urls if sorted_mirrors[0][0] in s] 242 | new_mirror = schema + matching[0] 243 | if verbose: 244 | print("\t- Your new mirror: " + new_mirror + "\n") 245 | 246 | temp = "sh -c \'echo \"\n# Autogenerated script by MirrorScripts-V2\" >> /etc/apt/sources.list\'" 247 | subprocess.Popen(temp, shell=True, stdout=subprocess.PIPE).stdout.read() 248 | 249 | line = "deb " + new_mirror + " kali-rolling main contrib non-free" 250 | temp = "sh -c \'echo %s >> /etc/apt/sources.list\'" 251 | subprocess.Popen(temp % line, shell=True, stdout=subprocess.PIPE).stdout.read() 252 | 253 | line = "deb-src " + new_mirror + " kali-rolling main contrib non-free" 254 | if not sources: 255 | line = "#" + line 256 | temp = "sh -c \'echo \"%s\" >> /etc/apt/sources.list\'" 257 | subprocess.Popen(temp % line, shell=True, stdout=subprocess.PIPE).stdout.read() 258 | 259 | print("[+] Done!") 260 | if verbose: 261 | print("\t- Run 'sudo apt clean; sudo apt update' for the changes to load.\n") 262 | else: 263 | print("") 264 | --------------------------------------------------------------------------------