import json import uuid import secrets import string from typing import Optional from shared .schemas import VlessConfig def generate_uuid ()->str : return str (uuid .uuid4 ()) def generate_short_id (length :int =8 )->str : return secrets .token_hex (length //2 ) def random_service_name (seed :int )->str : rng_chars =string .ascii_lowercase +string .digits r =__import__ ("random").Random (seed ) length =r .randint (6 ,20 ) return "".join (r .choice (rng_chars )for _ in range (length )) def build_server_config ( cfg :VlessConfig , vless_uuid :str , private_key :str , public_key :str , listen_ip :str ="0.0.0.0", )->dict : stream =_build_stream_settings_server (cfg ) inbound ={ "tag":"vless-in", "listen":listen_ip , "port":cfg .proxy_port , "protocol":"vless", "settings":{ "clients":[ { "id":vless_uuid , "flow":_pick_flow (cfg ), } ], "decryption":"none", }, "streamSettings":stream , "sniffing":{ "enabled":True , "destOverride":["http","tls","quic"], }, } inbound ["streamSettings"]["realitySettings"]={ "show":False , "dest":f"{cfg .dest_domain }:443", "xver":0 , "serverNames":[cfg .dest_domain ], "privateKey":private_key , "shortIds":[cfg .short_id ], "spiderX":cfg .spider_x , } config ={ "log":{"loglevel":"warning"}, "inbounds":[inbound ], "outbounds":[ {"tag":"direct","protocol":"freedom"}, {"tag":"block","protocol":"blackhole"}, ], "routing":{ "rules":[ {"type":"field","ip":["geoip:private"],"outboundTag":"block"}, ] }, } return config def _pick_flow (cfg :VlessConfig )->str : if cfg .transport_type =="tcp": return "xtls-rprx-vision" return "" def _build_stream_settings_server (cfg :VlessConfig )->dict : base ={ "network":cfg .transport_type , "security":"reality", } if cfg .transport_type =="grpc": base ["grpcSettings"]={ "serviceName":cfg .grpc_service_name , "multiMode":False , } elif cfg .transport_type =="xhttp": base ["xhttpSettings"]={ "mode":cfg .xhttp_mode , "path":cfg .spider_x or "/", "host":cfg .dest_domain , } return base def build_client_config ( cfg :VlessConfig , vless_uuid :str , server_ip :str , public_key :str , socks_port :int =10808 , http_port :int =10809 , )->dict : stream =_build_stream_settings_client (cfg ,public_key ) outbound ={ "tag":"proxy", "protocol":"vless", "settings":{ "vnext":[ { "address":server_ip , "port":cfg .proxy_port , "users":[ { "id":vless_uuid , "encryption":"none", "flow":_pick_flow (cfg ), } ], } ] }, "streamSettings":stream , } if cfg .mux_concurrency >0 : outbound ["mux"]={ "enabled":True , "concurrency":cfg .mux_concurrency , "xudpConcurrency":cfg .mux_concurrency , } if cfg .transport_type =="tcp"and cfg .fragment_strategy !="none": outbound ["streamSettings"]["sockopt"]={ "dialerProxy":"fragment", } config ={ "log":{"loglevel":"warning"}, "inbounds":[ { "tag":"socks", "listen":"127.0.0.1", "port":socks_port , "protocol":"socks", "settings":{"auth":"noauth","udp":True }, }, { "tag":"http", "listen":"127.0.0.1", "port":http_port , "protocol":"http", }, ], "outbounds":[outbound ,{"tag":"direct","protocol":"freedom"}], } if cfg .transport_type =="tcp"and cfg .fragment_strategy !="none": config ["outbounds"].append (_build_fragment_outbound (cfg )) return config def _build_stream_settings_client (cfg :VlessConfig ,public_key :str )->dict : base :dict ={ "network":cfg .transport_type , "security":"reality", "realitySettings":{ "fingerprint":cfg .fingerprint , "serverName":cfg .dest_domain , "publicKey":public_key , "shortId":cfg .short_id , "spiderX":cfg .spider_x , }, } if cfg .alpn : base ["realitySettings"]["alpn"]=cfg .alpn if cfg .transport_type =="grpc": base ["grpcSettings"]={ "serviceName":cfg .grpc_service_name , } elif cfg .transport_type =="xhttp": headers ={"Host":cfg .dest_domain } headers .update (cfg .extra_headers ) base ["xhttpSettings"]={ "mode":cfg .xhttp_mode , "path":cfg .spider_x or "/", "headers":headers , } return base def _build_fragment_outbound (cfg :VlessConfig )->dict : return { "tag":"fragment", "protocol":"freedom", "settings":{ "domainStrategy":"AsIs", }, "streamSettings":{ "sockopt":{ "dialerProxy":"", "tcpKeepAliveInterval":0 , } }, "fragment":{ "packets":cfg .fragment_strategy , "length":f"{cfg .fragment_length_min }-{cfg .fragment_length_max }", "interval":f"{cfg .fragment_interval_min }-{cfg .fragment_interval_max }", }, } def generate_reality_keys ()->tuple [str ,str ]: import subprocess result =subprocess .run ( ["xray","x25519"], capture_output =True ,text =True ,timeout =10 ) lines =result .stdout .strip ().splitlines () priv =lines [0 ].split (": ")[1 ].strip () pub =lines [1 ].split (": ")[1 ].strip () return priv ,pub def save_config (config :dict ,path :str ): with open (path ,"w")as f : json .dump (config ,f ,indent =2 )