#!/usr/bin/python # -*- coding:utf-8 -*- import json logLevel = 'warning' httpHeader = { 'type': 'http', 'request': { 'version': '1.1', 'method': 'GET', 'path': [], 'headers': { 'Host': [], 'User-Agent': [ 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36', 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/53.0.2785.109 Mobile/14A456 Safari/601.1.46' ], 'Accept-Encoding': [ 'gzip, deflate' ], 'Connection': [ 'keep-alive' ], 'Pragma': 'no-cache' } } } kcpSettings = { 'mtu': 1350, 'tti': 50, 'uplinkCapacity': 12, 'downlinkCapacity': 100, 'congestion': False, 'readBufferSize': 2, 'writeBufferSize': 2, 'header': {} } def __baseConfig(socksPort: int, outboundObject: dict) -> dict: # v2ray配置生成 return { 'log': { 'loglevel': logLevel }, 'inbounds': [ { 'port': socksPort, 'listen': '127.0.0.1', 'protocol': 'socks', 'settings': { 'udp': True, 'auth': 'noauth' } } ], 'outbounds': [ outboundObject ] } def __secureConfig(secureInfo: dict or None) -> dict: # TLS加密传输配置 if secureInfo is None: return {} tlsObject = { 'allowInsecure': not secureInfo['verify'], 'alpn': secureInfo['alpn'].split(',') } if secureInfo['sni'] != '': tlsObject['serverName'] = secureInfo['sni'] return { 'security': 'tls', 'tlsSettings': tlsObject } def __tcpConfig(streamInfo: dict) -> dict: # TCP传输方式配置 tcpObject = {} if streamInfo['obfs'] is not None: httpHeader['request']['path'].append(streamInfo['obfs']['path']) httpHeader['request']['headers']['Host'] = streamInfo['obfs']['host'].split(',') tcpObject['header'] = httpHeader return {**{ 'network': 'tcp', 'tcpSettings': tcpObject }, **__secureConfig(streamInfo['secure'])} def __kcpConfig(streamInfo: dict) -> dict: # mKCP传输方式配置 kcpObject = kcpSettings kcpObject['header']['type'] = streamInfo['obfs'] if streamInfo['seed'] is not None: kcpObject['seed'] = streamInfo['seed'] return {**{ 'network': 'kcp', 'kcpSettings': kcpObject }, **__secureConfig(streamInfo['secure'])} def __wsConfig(streamInfo: dict) -> dict: # WebSocket传输方式配置 wsObject = {} if streamInfo['path'] != '': wsObject['path'] = streamInfo['path'] if streamInfo['host'] != '': wsObject['headers'] = {} wsObject['headers']['Host'] = streamInfo['host'] if streamInfo['ed'] is not None: wsObject['maxEarlyData'] = streamInfo['ed'] wsObject['earlyDataHeaderName'] = 'Sec-WebSocket-Protocol' return {**{ 'network': 'ws', 'wsSettings': wsObject }, **__secureConfig(streamInfo['secure'])} def __h2Config(streamInfo: dict) -> dict: # HTTP/2传输方式配置 h2Object = { 'path': streamInfo['path'] } if streamInfo['host'] != '': h2Object['host'] = streamInfo['host'].split(',') return {**{ 'network': 'h2', 'httpSettings': h2Object }, **__secureConfig(streamInfo['secure'])} def __quicConfig(streamInfo: dict) -> dict: # QUIC传输方式配置 return {**{ 'network': 'quic', 'quicSettings': { 'security': streamInfo['method'], 'key': streamInfo['passwd'], 'header': { 'type': streamInfo['obfs'] } } }, **__secureConfig(streamInfo['secure'])} def __grpcConfig(streamInfo: dict) -> dict: # gRPC传输方式配置 return {**{ 'network': 'grpc', 'grpcSettings': { 'serviceName': streamInfo['service'] } }, **__secureConfig(streamInfo['secure'])} def __vmessConfig(proxyInfo: dict) -> dict: # VMess节点配置 streamType = proxyInfo['stream']['type'] if streamType == 'tcp': streamObject = __tcpConfig(proxyInfo['stream']) elif streamType == 'kcp': streamObject = __kcpConfig(proxyInfo['stream']) elif streamType == 'ws': streamObject = __wsConfig(proxyInfo['stream']) elif streamType == 'h2': streamObject = __h2Config(proxyInfo['stream']) elif streamType == 'quic': streamObject = __quicConfig(proxyInfo['stream']) elif streamType == 'grpc': streamObject = __grpcConfig(proxyInfo['stream']) else: raise Exception('Unknown stream type') return { 'protocol': 'vmess', 'settings': { 'vnext': [ { 'address': proxyInfo['server'], 'port': proxyInfo['port'], 'users': [ { 'id': proxyInfo['id'], 'alterId': proxyInfo['aid'], 'security': proxyInfo['method'] } ] } ] }, 'streamSettings': streamObject } def load(proxyInfo: dict, socksPort: int, configFile: str) -> tuple[list or None, str or None, dict or None]: """ VMess配置载入 proxyInfo: 节点信息 socksPort: 本地通讯端口 configFile: 配置文件路径 节点有误: return None, None, None 载入成功: return startCommand, fileContent, envVar """ try: config = __baseConfig(socksPort, __vmessConfig(proxyInfo)) return ['v2ray', '-c', configFile], json.dumps(config), {} except: return None, None, None