commit 327e813efbaf0b7ef3513115c5e12acbe8b50848 Author: Dreagonmon <531486058@qq.com> Date: Wed Mar 9 12:24:44 2022 +0800 v2xray init diff --git a/.bashrc b/.bashrc new file mode 100644 index 0000000..769cfeb --- /dev/null +++ b/.bashrc @@ -0,0 +1,30 @@ +# proxy +httpproxy-server () { + eval $(ps -ef | grep -m 1 "python .*xray_run\.py a" | awk '{print "sudo kill -9 "$2}') + nohup sudo python $HOME/scripts/v2xray/xray_run.py a >> /dev/null 2>&1 & +} + +httpproxy () { + export HTTP_PROXY="http://127.0.0.1:2802" + export http_proxy="http://127.0.0.1:2802" + export HTTPS_PROXY="http://127.0.0.1:2802" + export https_proxy="http://127.0.0.1:2802" + export FTP_PROXY="http://127.0.0.1:2802" + export ftp_proxy="http://127.0.0.1:2802" +} + +nohttpproxy () { + unset HTTP_PROXY + unset http_proxy + unset HTTPS_PROXY + unset https_proxy + unset FTP_PROXY + unset ftp_proxy +} + +getip () { + curl https://ip.gs +} + +# sudo groupadd -g 10333 tproxy +# sudo usermod -aG tproxy $USER diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d71f10b --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +__pycache__ +/config/* +!/config/xray +!/config/xray.* diff --git a/config/xray b/config/xray new file mode 100755 index 0000000..585732c Binary files /dev/null and b/config/xray differ diff --git a/kill.sh b/kill.sh new file mode 100755 index 0000000..e1d3eff --- /dev/null +++ b/kill.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +eval $(ps -ef | grep -m 1 "python .*xray_run\.py a" | awk '{print "sudo kill -9 "$2}') diff --git a/table.sh b/table.sh new file mode 100755 index 0000000..bc266ee --- /dev/null +++ b/table.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +ip rule add fwmark 1 table 100 +ip route add local 0.0.0.0/0 dev lo table 100 +ip -6 rule add fwmark 1 table 106 +ip -6 route add local ::/0 dev lo table 106 + +# ignore local address +iptables -t mangle -N XRAY +iptables -t mangle -A XRAY -d 10.0.0.0/8 -j RETURN +iptables -t mangle -A XRAY -d 100.64.0.0/10 -j RETURN +iptables -t mangle -A XRAY -d 127.0.0.0/8 -j RETURN +iptables -t mangle -A XRAY -d 169.254.0.0/16 -j RETURN +iptables -t mangle -A XRAY -d 172.16.0.0/12 -j RETURN +iptables -t mangle -A XRAY -d 192.0.0.0/24 -j RETURN +iptables -t mangle -A XRAY -d 224.0.0.0/4 -j RETURN +iptables -t mangle -A XRAY -d 240.0.0.0/4 -j RETURN +iptables -t mangle -A XRAY -d 255.255.255.255/32 -j RETURN +iptables -t mangle -A XRAY -d 192.168.0.0/16 -j RETURN +iptables -t mangle -A XRAY ! -s 192.168.31.5/24 -j RETURN +ip6tables -t mangle -N XRAY6 +ip6tables -t mangle -A XRAY6 -d FF00::0/8 -j RETURN +ip6tables -t mangle -A XRAY6 -d FE00::0/8 -j RETURN +ip6tables -t mangle -A XRAY6 -d 0000::0/8 -j RETURN +iptables -t mangle -N XRAY_SELF +iptables -t mangle -A XRAY_SELF -d 10.0.0.0/8 -j RETURN +iptables -t mangle -A XRAY_SELF -d 100.64.0.0/10 -j RETURN +iptables -t mangle -A XRAY_SELF -d 127.0.0.0/8 -j RETURN +iptables -t mangle -A XRAY_SELF -d 169.254.0.0/16 -j RETURN +iptables -t mangle -A XRAY_SELF -d 172.16.0.0/12 -j RETURN +iptables -t mangle -A XRAY_SELF -d 192.0.0.0/24 -j RETURN +iptables -t mangle -A XRAY_SELF -d 224.0.0.0/4 -j RETURN +iptables -t mangle -A XRAY_SELF -d 240.0.0.0/4 -j RETURN +iptables -t mangle -A XRAY_SELF -d 255.255.255.255/32 -j RETURN +iptables -t mangle -A XRAY_SELF -d 192.168.0.0/16 -j RETURN +ip6tables -t mangle -N XRAY6_SELF +ip6tables -t mangle -A XRAY6_SELF -d FF00::0/8 -j RETURN +ip6tables -t mangle -A XRAY6_SELF -d FE00::0/8 -j RETURN +ip6tables -t mangle -A XRAY6_SELF -d 0000::0/8 -j RETURN + +# config route +iptables -t mangle -A XRAY -p tcp -j TPROXY --on-ip 127.0.0.1 --on-port 2803 --tproxy-mark 1 +iptables -t mangle -A XRAY -p udp -j TPROXY --on-ip 127.0.0.1 --on-port 2803 --tproxy-mark 1 +ip6tables -t mangle -A XRAY6 -p udp -j TPROXY --on-ip ::1 --on-port 2803 --tproxy-mark 1 +ip6tables -t mangle -A XRAY6 -p tcp -j TPROXY --on-ip ::1 --on-port 2803 --tproxy-mark 1 +iptables -t mangle -A PREROUTING -j XRAY +ip6tables -t mangle -A PREROUTING -j XRAY6 +iptables -t mangle -A XRAY_SELF -j MARK --set-mark 1 +ip6tables -t mangle -A XRAY6_SELF -j MARK --set-mark 1 +iptables -t mangle -A OUTPUT -m owner --gid-owner 10333 -j XRAY_SELF +ip6tables -t mangle -A OUTPUT -m owner --gid-owner 10333 -j XRAY6_SELF diff --git a/xray_config.py b/xray_config.py new file mode 100644 index 0000000..fbcf33c --- /dev/null +++ b/xray_config.py @@ -0,0 +1,24 @@ +from os import path as _pth, mkdir as _mkdir +from json import load as _load, dump as _dump +CURRENT_DIR = _pth.abspath(_pth.dirname(__file__)) +CONFIG_DIR = _pth.join(CURRENT_DIR, "config") +CONFIG_FILE = _pth.join(CONFIG_DIR, "config.json") +if not _pth.exists(CONFIG_DIR): + _mkdir(CONFIG_DIR) + +class JSONConfig(dict): + def __init__(self, jsonpath): + self.__path = jsonpath + try: + with open(jsonpath, "r") as f: + super().__init__(_load(f)) + except: + super().__init__() + + def commit(self): + with open(self.__path, "w") as f: + _dump(self, f, indent=2) + +xray_manager_config = JSONConfig(_pth.join(CONFIG_DIR, "xray_manager.json")) +xray_config = JSONConfig(CONFIG_FILE) +xray_local_config = JSONConfig(_pth.join(CONFIG_DIR, "local.json")) diff --git a/xray_manager.py b/xray_manager.py new file mode 100644 index 0000000..ffd9344 --- /dev/null +++ b/xray_manager.py @@ -0,0 +1,256 @@ +import json +from os import path as _pth +CURRENT_DIR = _pth.abspath(_pth.dirname(__file__)) +import sys +sys.path.append(CURRENT_DIR) + +from urllib import request +from urllib.parse import unquote_plus +from re import match +from binascii import a2b_base64 +from xray_config import xray_manager_config, xray_local_config, xray_config +from math import ceil +from traceback import print_exc + +def fill_padding(base64_encode_str): + need_padding = len(base64_encode_str) % 4 != 0 + if need_padding: + missing_padding = 4 - need_padding + base64_encode_str += '=' * missing_padding + return base64_encode_str + +def base64_decode(base64_encode_str): + base64_encode_str = base64_encode_str.replace("-", "+").replace("_", "/") + base64_encode_str = fill_padding(base64_encode_str) + return a2b_base64(base64_encode_str).decode('utf8') + +def parse_format_sip002(line): + b64data = match(r"^ss:\/\/(.+?)@(.+):(.+?)(?:[\/\?].*?)?(#(.+))?$", line) + if b64data == None: + return None + account_info_b46 = b64data[1] + enc, passwd = base64_decode(account_info_b46).split(":") + server_addr = b64data[2] + server_port = b64data[3] + remarks = b64data[5].strip() + remarks = server_addr if remarks == None else unquote_plus(remarks, "utf8", errors='ignore') + return { + "protocol": "shadowsocks", + "settings": { + "servers": [ + { + "address": server_addr, + "port": int(server_port), + "password": passwd, + "method": enc + } + ] + }, + "remarks": remarks, + } + +def parse_format_default(line): + b64data = match(r"^(\w+?):\/\/(.*)$", line) + if b64data == None: + return None + protocol = b64data[1] + b64data = b64data[2] + data = base64_decode(b64data) + server_json = json.loads(data) + if protocol.lower() == "vless": + user = { + "id": server_json["id"], + "encryption": "none", + } + else: + user = { + "id": server_json["id"], + "alterId": int(server_json["aid"]), + "security": "auto", + } + stream = { + "network": server_json["net"], + } + if server_json["net"].lower() == "tcp": + if server_json["type"].lower() == "http": + stream["tcpSettings"] = { + "header": { + "type": "http", + "request": { + "headers": { + "Host": server_json["host"].split(","), + }, + }, + } + } + else: + stream["tcpSettings"] = {} + elif server_json["net"].lower() == "ws": + stream["wsSettings"] = { + "path": server_json["path"], + "headers": { + "Host": server_json["host"] + }, + } + elif server_json["net"].lower() == "h2": + stream["httpSettings"] = { + "host": [server_json["host"]], + "path": server_json["path"], + } + elif server_json["net"].lower() == "grpc": + stream["grpcSettings"] = { + "serviceName": server_json["path"], + } + else: + print(f"net {server_json['net'].lower()} not support:", server_json) + return None + if server_json["tls"] == "tls": + stream["security"] = "tls" + stream["tlsSettings"] = { + "serverName": server_json["sni"] + } + else: + stream["security"] = "none" + server = { + "protocol": protocol, + "settings": { + "vnext": [ + { + "address": server_json["add"], + "port": int(server_json["port"]), + "users": [ + user, + ], + }, + ], + }, + "streamSettings": stream, + "mux": { + "enabled": False, + "concurrency": 8, + }, + } + server["remarks"] = server_json["ps"] + return server + +def get_servers_from_subscribe_url(url): + servers = [] + try: + host = match(r"^(?:(?:https?)|(?:file)):\/\/([\w\.]*?)(?:[\/\?\#].*)?$", url)[1] + req = request.Request(url, headers={ + "Host": host, + "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:98.0) Gecko/20100101 Firefox/98.0", + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Language": "zh-CN,zh;q=0.7,en;q=0.3", + }, method="GET") + data = request.urlopen(req, timeout=5.0).read() + try: + text = a2b_base64(data).decode("utf8") + except: + text = data.decode("utf8") + except: + print_exc() + return servers + for line in text.split("\n"): + try: + server = parse_format_sip002(line) + server = parse_format_default(line) if server == None else server + if server != None: + servers.append(server) + except: + print(line) + print_exc() + return servers + +def main(): + loop = True + while loop: + try: + print("<==============================:") + print(": What do you want to do?") + print(": 1. Add a subscribe url.") + print(": 2. Remove a subscribe url.") + print(": 3. List all subscribe urls.") + print(": 4. Update servers from subscribe urls.") + print(": 5. Select the server from exists one.") + print(": q. Quit.") + func_sel = input(": Input a number to continue: ") + print(":==============================>") + if func_sel == "1": + url = input("> Input a url to add: ") + xray_manager_config.setdefault("subscribe", []).append(url) + xray_manager_config.commit() + elif func_sel == "2": + i = int(input("> Input the index to remove: ")) + if "subscribe" in xray_manager_config and len(xray_manager_config["subscribe"]) > i and i >= 0: + del xray_manager_config["subscribe"][i] + xray_manager_config.commit() + elif func_sel == "3": + subscribes = xray_manager_config.setdefault("subscribe", []) + for i in range(len(subscribes)): + print("{:< 4d}: {}".format(i, subscribes[i])) + if len(subscribes) <= 0: + print("Empty subscribe urls.") + elif func_sel == "4": + servers = [] + for url in xray_manager_config.setdefault("subscribe", []): + print("Fetching {}...".format(url)) + remote_servers = get_servers_from_subscribe_url(url) + print("Added {} server(s)".format(len(remote_servers))) + servers.extend(remote_servers) + xray_manager_config["servers"] = servers + xray_manager_config.commit() + elif func_sel == "5": + servers = xray_manager_config.setdefault("servers", []) + page_size = len(servers) + page_count = ceil(page_size / 5) + pages = 0 + loop2 = True + while loop2: + print("q : Give up.") + print("<<<<: Last page. '<' means 1 page, '<<' means 2 pages.") + print(">>>>: Next page. '>' means 1 page, '>>' means 2 pages.") + for i in range(pages*5, pages*5+5): + if i >= page_size: + break + print("{:< 4d}: {}".format(i, servers[i]["remarks"])) + print(": PAGE {}/{}".format(pages+1, page_count)) + num_sel = input("> Please input a number or operators to continue: ") + if num_sel.startswith("<"): + pages -= num_sel.count("<") + if pages < 0: + pages = 0 + elif num_sel.startswith(">"): + pages += num_sel.count(">") + if pages >= page_count: + pages = page_count - 1 + elif num_sel.lower() == "q": + loop2 = False + else: + index = -1 + try: + index = int(num_sel) + except: pass + if index >= 0 and index < page_size: + server = servers[index] + out = {} + for k in server: + if k in ["remarks"]: + continue + out[k] = server[k] + xray_config.clear() + for k in xray_local_config: + xray_config[k] = xray_local_config[k] + xray_config["outbounds"] = [out] + xray_config.commit() + loop2 = False + elif func_sel.lower() == "q": + loop = False + except KeyboardInterrupt: + loop = False + except: + print_exc() + print() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/xray_run.py b/xray_run.py new file mode 100644 index 0000000..3a0cc7b --- /dev/null +++ b/xray_run.py @@ -0,0 +1,21 @@ +''' + To kill the process: ps -ef | grep python +''' +from os import path as _pth +from time import sleep +CURRENT_DIR = _pth.abspath(_pth.dirname(__file__)) +XRAY_PATH = _pth.join(CURRENT_DIR, "config", "xray") + +def run(): + import os, xray_config, subprocess, signal + os.chdir(xray_config.CONFIG_DIR) + sleep(0.5) + p = subprocess.Popen([XRAY_PATH, "-c", xray_config.CONFIG_FILE]) + signal.signal(signal.SIGTERM, lambda a, b: p.send_signal(signal.SIGTERM)) + try: + p.wait() + except: + p.send_signal(signal.SIGTERM) + +if __name__ == "__main__": + run() \ No newline at end of file