public static List <Objects.Server> Parse(string text) { var list = new List <Objects.Server>(); try { if (text.StartsWith("tg://socks?") || text.StartsWith("https://t.me/socks?")) { var data = new Objects.Server(); data.Type = "Socks5"; var dict = new Dictionary <string, string>(); foreach (var str in text.Replace("tg://socks?", "").Replace("https://t.me/socks?", "").Split('&')) { var splited = str.Split('='); dict.Add(splited[0], splited[1]); } if (!dict.ContainsKey("server") || !dict.ContainsKey("port")) { return(null); } data.Address = dict["server"]; data.Port = int.Parse(dict["port"]); if (dict.ContainsKey("user") && !String.IsNullOrWhiteSpace(dict["user"])) { data.Username = dict["user"]; } if (dict.ContainsKey("pass") && !String.IsNullOrWhiteSpace(dict["pass"])) { data.Password = dict["pass"]; } list.Add(data); } else if (text.StartsWith("ss://")) { var data = new Objects.Server(); data.Type = "Shadowsocks"; try { if (!text.Contains("/?")) { var finder = new Regex(@"ss://(?<base64>[A-Za-z0-9+-/=_]+)(?:#(?<tag>\S+))?", RegexOptions.IgnoreCase); var parser = new Regex(@"^((?<method>.+?):(?<password>.*)@(?<hostname>.+?):(?<port>\d+?))$", RegexOptions.IgnoreCase); var match = finder.Match(text); if (!match.Success) { throw new FormatException(); } var base64 = match.Groups["base64"].Value.TrimEnd('/'); var tag = match.Groups["tag"].Value; if (!String.IsNullOrEmpty(tag)) { data.Remark = HttpUtility.UrlDecode(tag); } match = parser.Match(URLSafeBase64Decode(base64)); if (!match.Success) { throw new FormatException(); } data.Address = match.Groups["hostname"].Value; data.Port = int.Parse(match.Groups["port"].Value); data.Password = match.Groups["password"].Value; data.EncryptMethod = match.Groups["method"].Value; } else { if (text.Contains("#")) { data.Remark = HttpUtility.UrlDecode(text.Split('#')[1]); text = text.Split('#')[0]; } var finder = new Regex(@"ss://(?<base64>.+?)@(?<server>.+?):(?<port>\d+?)/\?plugin=(?<plugin>.+)"); var parser = new Regex(@"^(?<method>.+?):(?<password>.+)$"); var match = finder.Match(text); if (!match.Success) { throw new FormatException(); } data.Address = match.Groups["server"].Value; data.Port = int.Parse(match.Groups["port"].Value); var plugins = HttpUtility.UrlDecode(match.Groups["plugin"].Value).Split(';'); if (plugins[0] == "obfs-local") { plugins[0] = "simple-obfs"; } var base64 = URLSafeBase64Decode(match.Groups["base64"].Value); match = parser.Match(base64); if (!match.Success) { throw new FormatException(); } data.EncryptMethod = match.Groups["method"].Value; data.Password = match.Groups["password"].Value; data.OBFS = plugins[0]; data.OBFSParam = plugins[1]; } if (!Global.EncryptMethods.SS.Contains(data.EncryptMethod)) { Logging.Info(String.Format("不支持的 SS 加密方式:{0}", data.EncryptMethod)); return(null); } list.Add(data); } catch (FormatException) { try { var uri = new Uri(text); var userinfo = URLSafeBase64Decode(uri.UserInfo).Split(new char[] { ':' }, 2); if (userinfo.Length != 2) { return(null); } data.Remark = uri.GetComponents(UriComponents.Fragment, UriFormat.Unescaped); data.Address = uri.IdnHost; data.Port = uri.Port; data.Password = userinfo[1]; data.EncryptMethod = userinfo[0]; if (!Global.EncryptMethods.SS.Contains(data.EncryptMethod)) { Logging.Info(String.Format("不支持的 SS 加密方式:{0}", data.EncryptMethod)); return(null); } list.Add(data); } catch (UriFormatException) { return(null); } } } else if (text.StartsWith("ssd://")) { var json = Newtonsoft.Json.JsonConvert.DeserializeObject <Objects.SSD.Main>(URLSafeBase64Decode(text.Substring(6))); foreach (var server in json.servers) { var data = new Objects.Server(); data.Type = "Shadowsocks"; data.Remark = server.remarks; data.Address = server.server; data.Port = (server.port != 0) ? server.port : json.port; data.Password = (server.password != null) ? server.password : json.password; data.EncryptMethod = (server.encryption != null) ? server.encryption : json.encryption; if (Global.EncryptMethods.SS.Contains(data.EncryptMethod)) { list.Add(data); } } } else if (text.StartsWith("ssr://")) { var data = new Objects.Server(); data.Type = "ShadowsocksR"; text = text.Substring(6); var shadowsocksr = URLSafeBase64Decode(text).Split(':'); if (shadowsocksr.Length > 6) { var buff = ""; for (int i = 0; i < shadowsocksr.Length - 5; i++) { buff += shadowsocksr[i]; buff += ":"; } data.Address = buff.Substring(0, buff.Length - 1).Trim(); } else { data.Address = shadowsocksr[0]; } data.Port = int.Parse(shadowsocksr[shadowsocksr.Length - 5]); data.Protocol = shadowsocksr[shadowsocksr.Length - 4]; if (!Global.Protocols.Contains(data.Protocol)) { Logging.Info(String.Format("不支持的 SSR 协议:{0}", data.Protocol)); return(null); } data.EncryptMethod = shadowsocksr[shadowsocksr.Length - 3]; if (!Global.EncryptMethods.SSR.Contains(data.EncryptMethod)) { Logging.Info(String.Format("不支持的 SSR 加密方式:{0}", data.EncryptMethod)); return(null); } data.OBFS = shadowsocksr[shadowsocksr.Length - 2]; if (!Global.OBFSs.Contains(data.OBFS)) { Logging.Info(String.Format("不支持的 SSR 混淆:{0}", data.OBFS)); return(null); } var info = shadowsocksr[shadowsocksr.Length - 1].Split('/'); data.Password = URLSafeBase64Decode(info[0]); var dict = new Dictionary <string, string>(); if (info.Length > 1 && info[1].Length > 1) { foreach (var str in info[1].Substring(1).Split('&')) { var splited = str.Split('='); dict.Add(splited[0], splited[1]); } } if (dict.ContainsKey("remarks")) { data.Remark = URLSafeBase64Decode(dict["remarks"]); } if (dict.ContainsKey("protoparam")) { data.ProtocolParam = URLSafeBase64Decode(dict["protoparam"]); } if (dict.ContainsKey("obfsparam")) { data.OBFSParam = URLSafeBase64Decode(dict["obfsparam"]); } if (data.EncryptMethod != "none" && data.Protocol == "origin" && data.OBFS == "plain") { data.Type = "Shadowsocks"; } list.Add(data); } else if (text.StartsWith("vmess://")) { var data = new Objects.Server(); data.Type = "VMess"; text = text.Substring(8); var vmess = Newtonsoft.Json.JsonConvert.DeserializeObject <Objects.VMess>(URLSafeBase64Decode(text)); data.Remark = vmess.ps; data.Address = vmess.add; data.Port = vmess.port; data.UserID = vmess.id; data.AlterID = vmess.aid; data.TransferProtocol = vmess.net; if (!Global.TransferProtocols.Contains(data.TransferProtocol)) { Logging.Info(String.Format("不支持的 VMess 传输协议:{0}", data.TransferProtocol)); return(null); } data.FakeType = vmess.type; if (!Global.FakeTypes.Contains(data.FakeType)) { Logging.Info(String.Format("不支持的 VMess 伪装类型:{0}", data.FakeType)); return(null); } if (data.TransferProtocol == "quic") { if (!Global.EncryptMethods.VMessQUIC.Contains(vmess.host)) { Logging.Info(String.Format("不支持的 VMess QUIC 加密方式:{0}", vmess.host)); return(null); } else { data.QUICSecurity = vmess.host; data.QUICSecret = vmess.path; } } else { data.Host = vmess.host; data.Path = vmess.path; } data.TLSSecure = vmess.tls == "tls"; data.EncryptMethod = "auto"; // V2Ray 加密方式不包括在链接中,主动添加一个 list.Add(data); } else { System.Windows.Forms.MessageBox.Show("未找到可导入的链接!", "错误", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation); return(null); } } catch (Exception e) { Logging.Info(e.ToString()); return(null); } return(list); }
public static Objects.Server Parse(string text) { var data = new Objects.Server(); if (text.StartsWith("tg://socks?") || text.StartsWith("https://t.me/socks?")) { data.Type = "Socks5"; var dict = new Dictionary <string, string>(); foreach (var str in text.Replace("tg://socks?", "").Replace("https://t.me/socks?", "").Split('&')) { var splited = str.Split('='); dict.Add(splited[0], splited[1]); } if (!dict.ContainsKey("server") || !dict.ContainsKey("port")) { return(null); } data.Address = dict["server"]; data.Port = int.Parse(dict["port"]); if (dict.ContainsKey("user") && !String.IsNullOrWhiteSpace(dict["user"])) { data.Username = dict["user"]; } if (dict.ContainsKey("pass") && !String.IsNullOrWhiteSpace(dict["pass"])) { data.Password = dict["pass"]; } } else if (text.StartsWith("ss://")) { data.Type = "Shadowsocks"; try { var finder = new Regex(@"ss://(?<base64>[A-Za-z0-9+-/=_]+)(?:#(?<tag>\S+))?", RegexOptions.IgnoreCase); var parser = new Regex(@"^((?<method>.+?):(?<password>.*)@(?<hostname>.+?):(?<port>\d+?))$", RegexOptions.IgnoreCase); var match = finder.Match(text); if (!match.Success) { throw new FormatException(); } var base64 = match.Groups["base64"].Value.TrimEnd('/'); var tag = match.Groups["tag"].Value; if (!String.IsNullOrEmpty(tag)) { data.Remark = HttpUtility.UrlDecode(tag); } match = parser.Match(URLSafeBase64Decode(base64)); if (!match.Success) { throw new FormatException(); } data.Address = match.Groups["hostname"].Value; data.Port = int.Parse(match.Groups["port"].Value); data.Password = match.Groups["password"].Value; data.EncryptMethod = match.Groups["method"].Value; if (!Global.EncryptMethods.SS.Contains(data.EncryptMethod)) { Logging.Info(String.Format("不支持的 SS 加密方式:{0}", data.EncryptMethod)); return(null); } } catch (FormatException) { try { var uri = new Uri(text); var userinfo = URLSafeBase64Decode(uri.UserInfo).Split(new char[] { ':' }, 2); if (userinfo.Length != 2) { return(null); } data.Remark = uri.GetComponents(UriComponents.Fragment, UriFormat.Unescaped); data.Address = uri.IdnHost; data.Port = uri.Port; data.Password = userinfo[1]; data.EncryptMethod = userinfo[0]; if (!Global.EncryptMethods.SS.Contains(data.EncryptMethod)) { Logging.Info(String.Format("不支持的 SS 加密方式:{0}", data.EncryptMethod)); return(null); } } catch (UriFormatException) { return(null); } } } else if (text.StartsWith("ssr://")) { data.Type = "ShadowsocksR"; text = text.Substring(6); var shadowsocksr = URLSafeBase64Decode(text).Split(':'); data.Address = shadowsocksr[0]; data.Port = int.Parse(shadowsocksr[1]); data.Protocol = shadowsocksr[2]; if (!Global.Protocols.Contains(data.Protocol)) { Logging.Info(String.Format("不支持的 SSR 协议:{0}", data.Protocol)); return(null); } data.EncryptMethod = shadowsocksr[3]; if (!Global.EncryptMethods.SSR.Contains(data.EncryptMethod)) { Logging.Info(String.Format("不支持的 SSR 加密方式:{0}", data.EncryptMethod)); return(null); } data.OBFS = shadowsocksr[4]; if (!Global.OBFSs.Contains(data.OBFS)) { Logging.Info(String.Format("不支持的 SSR 混淆:{0}", data.OBFS)); return(null); } var info = shadowsocksr[5].Split('/'); data.Password = URLSafeBase64Decode(info[0]); var dict = new Dictionary <string, string>(); foreach (var str in info[1].Substring(1).Split('&')) { var splited = str.Split('='); dict.Add(splited[0], splited[1]); } if (dict.ContainsKey("remarks")) { data.Remark = URLSafeBase64Decode(dict["remarks"]); } if (dict.ContainsKey("protoparam")) { data.ProtocolParam = URLSafeBase64Decode(dict["protoparam"]); } if (dict.ContainsKey("obfsparam")) { data.OBFSParam = URLSafeBase64Decode(dict["obfsparam"]); } if (data.EncryptMethod != "none" && data.Protocol == "origin" && data.OBFS == "plain") { data.Type = "Shadowsocks"; } } else { return(null); } return(data); }
/// <summary> /// 启动 /// </summary> /// <param name="server">服务器</param> /// <param name="mode">模式</param> /// <returns>是否启动成功</returns> public bool Start(Objects.Server server, Objects.Mode mode) { if (!File.Exists("bin\\v2ray.exe") || !File.Exists("bin\\v2ctl.exe")) { return(false); } if (!Directory.Exists("data")) { Directory.CreateDirectory("data"); } File.WriteAllText("data\\last.json", Newtonsoft.Json.JsonConvert.SerializeObject(new Objects.Information.VMess.Config() { inbounds = new List <Objects.Information.VMess.Inbounds>() { new Objects.Information.VMess.Inbounds() { settings = new Objects.Information.VMess.InboundSettings() } }, outbounds = new List <Objects.Information.VMess.Outbounds>() { new Objects.Information.VMess.Outbounds() { settings = new Objects.Information.VMess.OutboundSettings() { vnext = new List <Objects.Information.VMess.VNext>() { new Objects.Information.VMess.VNext() { address = server.Address, port = server.Port, users = new List <Objects.Information.VMess.User> { new Objects.Information.VMess.User() { id = server.UserID, alterId = server.AlterID, security = server.EncryptMethod } } } } }, streamSettings = new Objects.Information.VMess.StreamSettings() { network = server.TransferProtocol, security = server.TLSSecure == true ? "tls" : "", wsSettings = server.TransferProtocol == "ws" ? new Objects.Information.VMess.WebSocketSettings() { path = server.Path == "" ? "/" : server.Path, headers = new Objects.Information.VMess.WSHeaders() { Host = server.Host == "" ? server.Address : server.Host } } : null, tcpSettings = server.FakeType == "http" ? new Objects.Information.VMess.TCPSettings() { header = new Objects.Information.VMess.TCPHeaders() { type = server.FakeType, request = new Objects.Information.VMess.TCPRequest() { path = server.Path == "" ? "/" : server.Path, headers = new Objects.Information.VMess.TCPRequestHeaders() { Host = server.Host == "" ? server.Address : server.Host } } } } : null, kcpSettings = server.TransferProtocol == "kcp" ? new Objects.Information.VMess.KCPSettings() { header = new Objects.Information.VMess.TCPHeaders() { type = server.FakeType } } : null, quicSettings = server.TransferProtocol == "quic" ? new Objects.Information.VMess.QUICSettings() { security = server.QUICSecurity, key = server.QUICSecret, header = new Objects.Information.VMess.TCPHeaders() { type = server.FakeType } } : null, httpSettings = server.TransferProtocol == "h2" ? new Objects.Information.VMess.HTTPSettings() { host = server.Host == "" ? server.Address : server.Host, path = server.Path == "" ? "/" : server.Path } : null, tlsSettings = new Objects.Information.VMess.TLSSettings() }, mux = new Objects.Information.VMess.OutboundMux() } }, routing = new Objects.Information.VMess.Routing() })); // 清理上一次的日志文件,防止淤积占用磁盘空间 if (Directory.Exists("logging")) { if (File.Exists("logging\\v2ray.log")) { File.Delete("logging\\v2ray.log"); } } Instance = MainController.GetProcess(); Instance.StartInfo.FileName = "bin\\v2ray.exe"; Instance.StartInfo.Arguments = "-config ..\\data\\last.json"; Instance.OutputDataReceived += OnOutputDataReceived; Instance.ErrorDataReceived += OnOutputDataReceived; State = Objects.State.Starting; Instance.Start(); Instance.BeginOutputReadLine(); Instance.BeginErrorReadLine(); for (int i = 0; i < 1000; i++) { Thread.Sleep(10); if (State == Objects.State.Started) { if (File.Exists("data\\last.json")) { File.Delete("data\\last.json"); } return(true); } if (State == Objects.State.Stopped) { Utils.Logging.Info("V2Ray 进程启动失败"); Stop(); return(false); } } Utils.Logging.Info("V2Ray 进程启动超时"); Stop(); return(false); }
/// <summary> /// 启动 /// </summary> /// <param name="server">配置</param> /// <returns>是否成功</returns> public bool Start(Objects.Server server, Objects.Mode mode) { foreach (var proc in Process.GetProcessesByName("tun2socks")) { try { proc.Kill(); } catch (Exception) { // 跳过 } } if (!File.Exists("bin\\tun2socks.exe")) { return(false); } if (File.Exists("logging\\tun2socks.log")) { File.Delete("logging\\tun2socks.log"); } SavedMode = mode; SavedServer = server; Configure(); SetupBypass(); Instance = new Process(); Instance.StartInfo.WorkingDirectory = String.Format("{0}\\bin", Directory.GetCurrentDirectory()); Instance.StartInfo.FileName = String.Format("{0}\\bin\\tun2socks.exe", Directory.GetCurrentDirectory()); string dns; if (Global.TUNTAP.UseCustomDNS) { dns = ""; foreach (var value in Global.TUNTAP.DNS) { dns += value; dns += ','; } dns = dns.Trim(); dns = dns.Substring(0, dns.Length - 1); } else { pDNSController.Start(); dns = "127.0.0.1"; } if (Global.TUNTAP.UseFakeDNS) { dns += " -fakeDns"; } if (server.Type == "Socks5") { Instance.StartInfo.Arguments = String.Format("-proxyServer {0}:{1} -tunAddr {2} -tunMask {3} -tunGw {4} -tunDns {5}", server.Address, server.Port, Global.TUNTAP.Address, Global.TUNTAP.Netmask, Global.TUNTAP.Gateway, dns); } else { Instance.StartInfo.Arguments = String.Format("-proxyServer 127.0.0.1:2801 -tunAddr {0} -tunMask {1} -tunGw {2} -tunDns {3}", Global.TUNTAP.Address, Global.TUNTAP.Netmask, Global.TUNTAP.Gateway, dns); } Instance.StartInfo.CreateNoWindow = true; Instance.StartInfo.RedirectStandardError = true; Instance.StartInfo.RedirectStandardInput = true; Instance.StartInfo.RedirectStandardOutput = true; Instance.StartInfo.UseShellExecute = false; Instance.EnableRaisingEvents = true; Instance.ErrorDataReceived += OnOutputDataReceived; Instance.OutputDataReceived += OnOutputDataReceived; State = Objects.State.Starting; Instance.Start(); Instance.BeginErrorReadLine(); Instance.BeginOutputReadLine(); Instance.PriorityClass = ProcessPriorityClass.RealTime; for (int i = 0; i < 1000; i++) { Thread.Sleep(10); if (State == Objects.State.Started) { return(true); } if (State == Objects.State.Stopped) { Stop(); return(false); } } return(false); }
/// <summary> /// 启动 /// </summary> /// <param name="server">服务器</param> /// <param name="mode">模式</param> /// <returns>是否成功</returns> public bool Start(Objects.Server server, Objects.Mode mode) { if (!File.Exists("bin\\Redirector.exe")) { return(false); } if (File.Exists("logging\\redirector.log")) { File.Delete("logging\\redirector.log"); } // 生成驱动文件路径 var driver = String.Format("{0}\\drivers\\netfilter2.sys", Environment.SystemDirectory); // 检查驱动是否存在 if (!File.Exists(driver)) { // 生成系统版本 var version = $"{Environment.OSVersion.Version.Major.ToString()}.{Environment.OSVersion.Version.Minor.ToString()}"; // 检查系统版本并复制对应驱动 try { switch (version) { case "10.0": File.Copy("bin\\Win-10.sys", driver); Utils.Logging.Info("已复制 Win10 驱动"); break; case "6.3": case "6.2": File.Copy("bin\\Win-8.sys", driver); Utils.Logging.Info("已复制 Win8 驱动"); break; case "6.1": case "6.0": File.Copy("bin\\Win-7.sys", driver); Utils.Logging.Info("已复制 Win7 驱动"); break; default: Utils.Logging.Info($"不支持的系统版本:{version}"); return(false); } } catch (Exception e) { Utils.Logging.Info("复制驱动文件失败"); Utils.Logging.Info(e.ToString()); return(false); } // 注册驱动文件 var result = nfapinet.NFAPI.nf_registerDriver("netfilter2"); if (result != nfapinet.NF_STATUS.NF_STATUS_SUCCESS) { Utils.Logging.Info($"注册驱动失败,返回值:{result}"); return(false); } } try { var service = new ServiceController("netfilter2"); if (service.Status == ServiceControllerStatus.Stopped) { service.Start(); } } catch (Exception e) { Utils.Logging.Info(e.ToString()); var result = nfapinet.NFAPI.nf_registerDriver("netfilter2"); if (result != nfapinet.NF_STATUS.NF_STATUS_SUCCESS) { Utils.Logging.Info($"注册驱动失败,返回值:{result}"); return(false); } } var processes = ""; foreach (var proc in mode.Rule) { processes += proc; processes += ","; } processes = processes.Substring(0, processes.Length - 1); Instance = MainController.GetProcess(); Instance.StartInfo.FileName = "bin\\Redirector.exe"; Instance.StartInfo.Arguments = String.Format("-r 127.0.0.1:2801 -p \"{0}\"", processes); if (server.Type == "Socks5") { var result = Utils.DNS.Lookup(server.Address); if (result == null) { Utils.Logging.Info("无法解析服务器 IP 地址"); return(false); } Instance.StartInfo.Arguments = String.Format("-r {0}:{1} -p \"{2}\"", result.ToString(), server.Port, processes); if (!String.IsNullOrWhiteSpace(server.Username) && !String.IsNullOrWhiteSpace(server.Password)) { Instance.StartInfo.Arguments += String.Format(" -username \"{0}\" -password \"{1}\"", server.Username, server.Password); } } Instance.OutputDataReceived += OnOutputDataReceived; Instance.ErrorDataReceived += OnOutputDataReceived; State = Objects.State.Starting; Instance.Start(); Instance.BeginOutputReadLine(); Instance.BeginErrorReadLine(); for (int i = 0; i < 1000; i++) { Thread.Sleep(10); if (State == Objects.State.Started) { return(true); } if (State == Objects.State.Stopped) { Utils.Logging.Info("NF 进程启动失败"); Stop(); return(false); } } Utils.Logging.Info("NF 进程启动超时"); Stop(); return(false); }
/// <summary> /// 启动 /// </summary> /// <param name="server">服务器</param> /// <param name="mode">模式</param> /// <returns>是否启动成功</returns> public bool Start(Objects.Server server, Objects.Mode mode) { foreach (var proc in Process.GetProcessesByName("Shadowsocks")) { try { proc.Kill(); } catch (Exception) { // 跳过 } } if (!File.Exists("bin\\Shadowsocks.exe")) { return(false); } // 清理上一次的日志文件,防止淤积占用磁盘空间 if (Directory.Exists("logging")) { if (File.Exists("logging\\shadowsocks.log")) { File.Delete("logging\\shadowsocks.log"); } } Instance = MainController.GetProcess(); Instance.StartInfo.FileName = "bin\\Shadowsocks.exe"; if (!String.IsNullOrWhiteSpace(server.Plugin) && !String.IsNullOrWhiteSpace(server.PluginOptions)) { Instance.StartInfo.Arguments = String.Format("-s {0} -p {1} -b 0.0.0.0 -l 2801 -m {2} -k \"{3}\" -u --plugin {4} --plugin-opts \"{5}\"", server.Address, server.Port, server.EncryptMethod, server.Password, server.Plugin, server.PluginOptions); } else { Instance.StartInfo.Arguments = String.Format("-s {0} -p {1} -b 0.0.0.0 -l 2801 -m {2} -k \"{3}\" -u", server.Address, server.Port, server.EncryptMethod, server.Password); } if (mode.BypassChina) { Instance.StartInfo.Arguments += " --acl default.acl"; } Instance.OutputDataReceived += OnOutputDataReceived; Instance.ErrorDataReceived += OnOutputDataReceived; State = Objects.State.Starting; Instance.Start(); Instance.BeginOutputReadLine(); Instance.BeginErrorReadLine(); for (int i = 0; i < 1000; i++) { Thread.Sleep(10); if (State == Objects.State.Started) { return(true); } if (State == Objects.State.Stopped) { Utils.Logging.Info("SS 进程启动失败"); Stop(); return(false); } } Utils.Logging.Info("SS 进程启动超时"); Stop(); return(false); }
/// <summary> /// 启动 /// </summary> /// <param name="server">服务器</param> /// <param name="mode">模式</param> /// <returns>是否启动成功</returns> public bool Start(Objects.Server server, Objects.Mode mode) { var result = false; switch (server.Type) { case "Socks5": if (mode.Type == 4) { result = false; } else { result = true; } break; case "Shadowsocks": KillProcess("Shadowsocks"); if (pSSController == null) { pSSController = new SSController(); } result = pSSController.Start(server, mode); break; case "ShadowsocksR": KillProcess("ShadowsocksR"); if (pSSRController == null) { pSSRController = new SSRController(); } result = pSSRController.Start(server, mode); break; case "VMess": KillProcess("v2ray"); if (pVMessController == null) { pVMessController = new VMessController(); } result = pVMessController.Start(server, mode); break; default: break; } if (result) { if (mode.Type == 0) { if (pNFController == null) { pNFController = new NFController(); } // 进程代理模式,启动 NF 控制器 result = pNFController.Start(server, mode); } else if (mode.Type == 1) { if (pTUNTAPController == null) { pTUNTAPController = new TUNTAPController(); } // TUN/TAP 黑名单代理模式,启动 TUN/TAP 控制器 result = pTUNTAPController.Start(server, mode); } else if (mode.Type == 2) { if (pTUNTAPController == null) { pTUNTAPController = new TUNTAPController(); } // TUN/TAP 白名单代理模式,启动 TUN/TAP 控制器 result = pTUNTAPController.Start(server, mode); } else if (mode.Type == 3 || mode.Type == 5) { if (pHTTPController == null) { pHTTPController = new HTTPController(); } // HTTP 系统代理和 Socks5 和 HTTP 代理模式,启动 HTTP 控制器 result = pHTTPController.Start(server, mode); } else if (mode.Type == 4) { // Socks5 代理模式,不需要启动额外的控制器 } else { result = false; } } if (!result) { Stop(); } return(result); }
/// <summary> /// 生成分享链接 /// </summary> /// <param name="server"></param> /// <returns></returns> public static string Generate(Objects.Server server) { return(String.Empty); }
/// <summary> /// 解析分享链接 /// </summary> /// <param name="server"></param> /// <returns></returns> public static Objects.Server Parse(string text) { var data = new Objects.Server(); if (text.StartsWith("ss://")) { data.Type = "Shadowsocks"; try { var finder = new Regex("^(?i)ss://([A-Za-z0-9+-/=_]+)(#(.+))?", RegexOptions.IgnoreCase); var parser = new Regex("^((?<method>.+):(?<password>.*)@(?<address>.+?):(?<port>\\d+?))$", RegexOptions.IgnoreCase); var match = finder.Match(text); if (!match.Success) { throw new FormatException(); } match = parser.Match(UrlSafeBase64Decode(match.Groups[1].Value)); data.Address = match.Groups["address"].Value; data.Port = int.Parse(match.Groups["port"].Value); data.Password = match.Groups["password"].Value; data.EncryptMethod = match.Groups["method"].Value; if (!Global.EncryptMethods.SS.Contains(data.EncryptMethod)) { Logging.Info(String.Format("不支持的 SS 加密方式:{0}", data.EncryptMethod)); return(null); } } catch (FormatException) { var uri = new Uri(text); var userinfo = UrlSafeBase64Decode(uri.UserInfo).Split(':'); data.Remark = uri.GetComponents(UriComponents.Fragment, UriFormat.Unescaped); data.Address = uri.IdnHost; data.Port = uri.Port; if (!Global.EncryptMethods.SS.Contains(data.EncryptMethod)) { Logging.Info(String.Format("不支持的 SS 加密方式:{0}", data.EncryptMethod)); return(null); } } } else if (text.StartsWith("ssr://")) { data.Type = "ShadowsocksR"; text = text.Substring(6); var shadowsocksr = UrlSafeBase64Decode(text).Split(':'); data.Address = shadowsocksr[0]; data.Port = int.Parse(shadowsocksr[1]); data.Protocol = shadowsocksr[2]; if (!Global.Protocols.Contains(data.Protocol)) { Logging.Info(String.Format("不支持的 SSR 协议:{0}", data.Protocol)); return(null); } data.EncryptMethod = shadowsocksr[3]; if (!Global.EncryptMethods.SSR.Contains(data.EncryptMethod)) { Logging.Info(String.Format("不支持的 SSR 加密方式:{0}", data.EncryptMethod)); return(null); } data.OBFS = shadowsocksr[4]; if (!Global.OBFSs.Contains(data.OBFS)) { Logging.Info(String.Format("不支持的 SSR 混淆:{0}", data.OBFS)); return(null); } var info = shadowsocksr[5].Split('/'); data.Password = UrlSafeBase64Decode(info[0]); var dict = new Dictionary <string, string>(); foreach (var str in info[1].Substring(1).Split('&')) { var splited = str.Split('='); dict.Add(splited[0], splited[1]); } if (dict.ContainsKey("remarks")) { data.Remark = UrlSafeBase64Decode(dict["remarks"]); } if (dict.ContainsKey("protoparam")) { data.ProtocolParam = UrlSafeBase64Decode(dict["protoparam"]); } if (dict.ContainsKey("obfsparam")) { data.OBFSParam = UrlSafeBase64Decode(dict["obfsparam"]); } if (data.EncryptMethod != "none" && data.Protocol == "origin" && data.OBFS == "plain") { data.Type = "Shadowsocks"; } } else if (text.StartsWith("vmess://")) { data.Type = "VMess"; text = text.Substring(8); var vmess = SimpleJSON.JSON.Parse(UrlSafeBase64Decode(text)); data.Remark = vmess["ps"].Value; data.Address = vmess["add"].Value; data.Port = vmess["port"].AsInt; data.UserID = vmess["id"].Value; data.AlterID = vmess["aid"].AsInt; data.TransferProtocol = vmess["net"].Value; if (!Global.TransferProtocols.Contains(data.TransferProtocol)) { Logging.Info(String.Format("不支持的 VMess 传输协议:{0}", data.TransferProtocol)); return(null); } data.FakeType = vmess["type"].Value; if (!Global.FakeTypes.Contains(data.FakeType)) { Logging.Info(String.Format("不支持的 VMess 伪装类型:{0}", data.FakeType)); return(null); } data.Host = vmess["host"].Value; data.Path = vmess["path"].Value; data.TLSSecure = vmess["tls"].Value == "tls"; } else { return(null); } return(data); }
/// <summary> /// 启动 /// </summary> /// <param name="server">服务器</param> /// <param name="mode">模式</param> /// <returns>是否启动成功</returns> public bool Start(Objects.Server server, Objects.Mode mode) { if (!File.Exists("bin\\Shadowsocks.exe")) { return(false); } // 清理上一次的日志文件,防止淤积占用磁盘空间 if (Directory.Exists("logging")) { if (File.Exists("logging\\shadowsocks.log")) { File.Delete("logging\\shadowsocks.log"); } } Instance = MainController.GetProcess(); Instance.StartInfo.FileName = "bin\\Shadowsocks.exe"; if (!String.IsNullOrWhiteSpace(server.OBFS) && !String.IsNullOrWhiteSpace(server.OBFSParam)) { Instance.StartInfo.Arguments = $"-s {server.Address} -p {server.Port} -b {Global.Settings.LocalAddress} -l {Global.Settings.Socks5LocalPort} -m {server.EncryptMethod} -k \"{server.Password}\" -u --plugin {server.OBFS} --plugin-opts \"{server.OBFSParam}\""; } else { Instance.StartInfo.Arguments = $"-s {server.Address} -p {server.Port} -b {Global.Settings.LocalAddress} -l {Global.Settings.Socks5LocalPort} -m {server.EncryptMethod} -k \"{server.Password}\" -u"; } if (mode.BypassChina) { Instance.StartInfo.Arguments += " --acl default.acl"; } Instance.OutputDataReceived += OnOutputDataReceived; Instance.ErrorDataReceived += OnOutputDataReceived; State = Objects.State.Starting; Instance.Start(); Instance.BeginOutputReadLine(); Instance.BeginErrorReadLine(); for (int i = 0; i < 1000; i++) { Thread.Sleep(10); if (State == Objects.State.Started) { return(true); } if (State == Objects.State.Stopped) { Utils.Logging.Info("SS 进程启动失败"); Stop(); return(false); } } Utils.Logging.Info("SS 进程启动超时"); Stop(); return(false); }
/// <summary> /// 启动 /// </summary> /// <param name="server">配置</param> /// <returns>是否成功</returns> public bool Start(Objects.Server server) { if (server.Type == "Shadowsocks") { SSController = new SSController(); if (!SSController.Start(server)) { return(false); } } else if (server.Type == "ShadowsocksR") { SRController = new SRController(); if (!SRController.Start(server)) { return(false); } } Instance = new Process(); Instance.StartInfo.WorkingDirectory = String.Format("{0}\\Bin", Directory.GetCurrentDirectory()); Instance.StartInfo.FileName = String.Format("{0}\\Bin\\tun2socks.exe", Directory.GetCurrentDirectory()); var dns = "8.8.8.8"; if (Global.TUNTAP.UseCustomDNS) { dns = ""; foreach (var value in Global.TUNTAP.DNS) { dns += value; dns += ','; } dns = dns.Trim(); dns = dns.Substring(0, dns.Length - 1); } if (server.Type == "Socks5") { Instance.StartInfo.Arguments = String.Format("-proxyServer {0}:{1} -tunAddr {2} -tunMask {3} -tunGw {4} -tunDns {5}", server.Address, server.Port, Global.TUNTAP.Address, Global.TUNTAP.Netmask, Global.TUNTAP.Gateway, dns); } else if (server.Type == "VMess") { var data = new Objects.Information.Main(); var outbound = new Objects.Information.Outbound() { tag = "defaultOutbound" }; if (server.Type == "VMess") { outbound.protocol = "vmess"; var settings = new Objects.Information.Protocol.Outbound.VMess(); settings.vnext.Add(new Objects.Information.Protocol.Outbound.VMessServer() { address = server.Address, port = server.Port, users = new List <Objects.Information.Protocol.Outbound.VMessUser>() { new Objects.Information.Protocol.Outbound.VMessUser() { id = server.UserID, alterId = server.AlterID, security = "auto" } } }); outbound.settings = settings; outbound.streamSettings = new Objects.Information.OutboundStream(); outbound.streamSettings.network = server.TransferProtocol; outbound.streamSettings.security = server.TLSSecure ? "tls" : "none"; switch (server.TransferProtocol) { case "tcp": outbound.streamSettings.network = "tcp"; if (server.FakeType == "http") { var tcpSettings = new Objects.Information.OutboundStreamTCP() { header = new Objects.Information.OutboundStreamTCPHTTPHeader() { request = new Objects.Information.OutboundStreamTCPHTTPRequestHeader() { headers = new Dictionary <string, List <string> >() { { "Host", new List <string>() { server.Host } } } } } }; } break; case "kcp": outbound.streamSettings.network = "kcp"; outbound.streamSettings.kcpSettings = new Objects.Information.OutboundStreamKCP() { header = new Dictionary <string, string>() { { "type", server.FakeType } } }; break; case "ws": outbound.streamSettings.network = "ws"; var wsSettings = new Objects.Information.OutboundStreamWebSocket() { path = server.Path }; if (server.Host != "") { wsSettings.headers.Add("Host", server.Host); } outbound.streamSettings.wsSettings = wsSettings; break; case "http": outbound.streamSettings.network = "http"; var httpSettings = new Objects.Information.OutboundStreamHTTP2(); if (server.Host != "") { httpSettings.host = new List <string>() { server.Host }; } httpSettings.path = server.Path; outbound.streamSettings.httpSettings = httpSettings; break; case "quic": outbound.streamSettings.network = "quic"; outbound.streamSettings.quicSettings = new Objects.Information.OutboundStreamQUIC() { header = new Dictionary <string, string>() { { "type", server.FakeType } }, security = server.QUICSecurity, key = server.QUICSecret }; break; default: outbound.streamSettings.network = "tcp"; break; } } data.outbounds.Add(outbound); File.WriteAllText("Data\\V2RayLast.json", Newtonsoft.Json.JsonConvert.SerializeObject(data)); Instance.StartInfo.Arguments = String.Format("-vconfig \"{0}\" -tunAddr {1} -tunMask {2} -tunGw {3} -tunDns {4}", String.Format("{0}\\Data\\V2RayLast.json", Directory.GetCurrentDirectory()), Global.TUNTAP.Address, Global.TUNTAP.Netmask, Global.TUNTAP.Gateway, dns); } else { Instance.StartInfo.Arguments = String.Format("-proxyServer 127.0.0.1:2810 -tunAddr {0} -tunMask {1} -tunGw {2} -tunDns {3}", Global.TUNTAP.Address, Global.TUNTAP.Netmask, Global.TUNTAP.Gateway, dns); } Instance.StartInfo.CreateNoWindow = true; Instance.StartInfo.RedirectStandardError = true; Instance.StartInfo.RedirectStandardInput = true; Instance.StartInfo.RedirectStandardOutput = true; Instance.StartInfo.UseShellExecute = false; Instance.EnableRaisingEvents = true; Instance.ErrorDataReceived += OnOutputDataReceived; Instance.OutputDataReceived += OnOutputDataReceived; State = Objects.State.Starting; Instance.Start(); Instance.BeginErrorReadLine(); Instance.BeginOutputReadLine(); for (int i = 0; i < 1000; i++) { Thread.Sleep(10); if (State == Objects.State.Started) { return(true); } if (State == Objects.State.Stopped) { Stop(); return(false); } } return(false); }
/// <summary> /// 启动 /// </summary> /// <param name="server">服务器</param> /// <returns>是否成功</returns> public bool Start(Objects.Server server) { if (!File.Exists("bin\\ShadowsocksR.exe")) { return(false); } if (!Directory.Exists("data")) { Directory.CreateDirectory("data"); } File.WriteAllText("data\\last.json", Newtonsoft.Json.JsonConvert.SerializeObject(new Objects.Information.SSR() { server = server.Address, server_port = server.Port, password = server.Password, method = server.EncryptMethod, protocol = server.Protocol, protocol_param = server.ProtocolParam, obfs = server.OBFS, obfs_param = server.OBFSParam })); // 清理上一次的日志文件,防止淤积占用磁盘空间 if (Directory.Exists("logging")) { if (File.Exists("logging\\shadowsocksr.log")) { File.Delete("logging\\shadowsocksr.log"); } } Instance = MainController.GetProcess(); Instance.StartInfo.FileName = "bin\\ShadowsocksR.exe"; Instance.StartInfo.Arguments = "-c ..\\data\\last.json -u"; Instance.OutputDataReceived += OnOutputDataReceived; Instance.ErrorDataReceived += OnOutputDataReceived; State = Objects.State.Starting; Instance.Start(); Instance.BeginOutputReadLine(); Instance.BeginErrorReadLine(); for (int i = 0; i < 1000; i++) { Thread.Sleep(10); if (State == Objects.State.Started) { if (File.Exists("data\\last.json")) { File.Delete("data\\last.json"); } return(true); } if (State == Objects.State.Stopped) { Utils.Logging.Info("SSR 进程启动失败"); Stop(); return(false); } } Utils.Logging.Info("SSR 进程启动超时"); Stop(); return(false); }
/// <summary> /// 启动 /// </summary> /// <param name="server">服务器</param> /// <param name="mode">模式</param> /// <returns>是否启动成功</returns> public bool Start(Objects.Server server, Objects.Mode mode) { var result = false; switch (server.Type) { case "Socks5": result = true; break; case "Shadowsocks": result = pSSController.Start(server, mode); break; case "ShadowsocksR": result = pSSRController.Start(server, mode); break; case "VMess": result = pVMessController.Start(server, mode); break; default: break; } if (result) { if (mode.Type == 0) { result = pNFController.Start(server, mode); } else if (mode.Type == 1) { result = pTUNTAPController.Start(server, mode); } else if (mode.Type == 2) { result = pTUNTAPController.Start(server, mode); } else if (mode.Type == 3 || mode.Type == 5) { result = pHTTPController.Start(server, mode); } else if (mode.Type == 4) { // 跳过 } else { result = false; } } if (!result) { Stop(); } return(result); }
public Objects.Server ParseServer(string text) { var json = SimpleJSON.JSON.Parse(Encoding.UTF8.GetString(Convert.FromBase64String(text.Replace("vmess://", "")))); var server = new Objects.Server() { ID = Guid.NewGuid().ToString(), Remark = json["ps"].Value, Address = json["add"].Value, Port = json["port"].AsInt, UserID = json["id"].Value, AlterID = json["aid"].AsInt, Path = (json["path"].Value == "") ? "/" : json["path"].Value, TLSSecure = (json["tls"].Value == "") ? false : true }; switch (json["net"].Value) { case "tcp": server.TransferMethod = "TCP"; break; case "kcp": server.TransferMethod = "mKCP"; break; case "ws": server.TransferMethod = "WebSockets"; break; case "h2": server.TransferMethod = "HTTP/2"; break; case "quic": server.TransferMethod = "QUIC"; break; default: server.TransferMethod = "TCP"; break; } switch (json["type"].Value) { case "none": server.FakeType = "None"; break; case "http": server.FakeType = "HTTP"; break; case "srtp": server.FakeType = "SRTP"; break; case "utp": server.FakeType = "UTP"; break; case "dtls": server.FakeType = "DTLS"; break; case "wireguard": server.FakeType = "WireGuard"; break; case "wechat-video": server.FakeType = "WeChat"; break; default: server.FakeType = "None"; break; } return(server); }