ssr、订阅内容解析

网络 专栏收录该内容
4 篇文章 0 订阅

 

// ssr地址解析
var ssrObj = new SSR.Server("ssr://xxx", "");
ssrObj.remarks = "ssr name";
var ssrUrl = ssrObj.GetSSRLinkForServer();

// ssr地址与订阅内容转换
var ssrUrls = new[] { "ssr:\\xxx","ssr:\\xxx"};
var subscribeContent = SSR.Subscriber.ToSubscribeStr(ssrUrls);
var ssrUrls2 = SSR.Subscriber.FromSubscribeStr(subscribeContent);

 

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

namespace WebApplication1
{
    public class SSR
    {
        /// <summary>
        /// SS、SSR地址编解码
        /// </summary>
        [Serializable]
        public class Server
        {
            public string id;
            public string server;
            public int server_port;
            public int server_udp_port;
            public string password;
            public string method;
            public string protocol;
            public string protocolparam;
            public string obfs;
            public string obfsparam;
            public string remarks_base64;
            public string group;
            public bool enable;
            public bool udp_over_tcp;
            public int latency;
            public static int LATENCY_ERROR = -2;
            public static int LATENCY_PENDING = -1;
            public static int LATENCY_TESTING = 0;
            private object protocoldata;
            private object obfsdata;
            private static Server forwardServer = new Server();
            public string remarks
            {
                get
                {
                    if (this.remarks_base64.Length == 0)
                    {
                        return string.Empty;
                    }
                    string result;
                    try
                    {
                        result = Base64.DecodeUrlSafeBase64(this.remarks_base64);
                    }
                    catch (FormatException)
                    {
                        string text = this.remarks_base64;
                        this.remarks = this.remarks_base64;
                        result = text;
                    }
                    return result;
                }
                set
                {
                    this.remarks_base64 = Base64.EncodeUrlSafeBase64(value, true);
                }
            }
            public void CopyServer(Server Server)
            {
                this.protocoldata = Server.protocoldata;
                this.obfsdata = Server.obfsdata;
                this.enable = Server.enable;
            }
            public void CopyServerInfo(Server Server)
            {
                this.remarks = Server.remarks;
                this.group = Server.group;
            }
            public static Server GetForwardServerRef()
            {
                return Server.forwardServer;
            }
            public string FriendlyName()
            {
                if (string.IsNullOrEmpty(this.server))
                {
                    return "New server";
                }
                if (string.IsNullOrEmpty(this.remarks_base64))
                {
                    if (this.server.IndexOf(':') >= 0)
                    {
                        return string.Concat(new object[]
                        {
                        "[",
                        this.server,
                        "]:",
                        this.server_port
                        });
                    }
                    return this.server + ":" + this.server_port;
                }
                else
                {
                    if (this.server.IndexOf(':') >= 0)
                    {
                        return string.Concat(new object[]
                        {
                        this.remarks,
                        " ([",
                        this.server,
                        "]:",
                        this.server_port,
                        ")"
                        });
                    }
                    return string.Concat(new object[]
                    {
                    this.remarks,
                    " (",
                    this.server,
                    ":",
                    this.server_port,
                    ")"
                    });
                }
            }
            public string HiddenName(bool hide = true)
            {
                if (string.IsNullOrEmpty(this.server))
                {
                    return "New server";
                }
                string text = this.server;
                if (hide)
                {
                    text = ServerName.HideServerAddr(this.server);
                }
                if (string.IsNullOrEmpty(this.remarks_base64))
                {
                    if (this.server.IndexOf(':') >= 0)
                    {
                        return string.Concat(new object[]
                        {
                        "[",
                        text,
                        "]:",
                        this.server_port
                        });
                    }
                    return text + ":" + this.server_port;
                }
                else
                {
                    if (this.server.IndexOf(':') >= 0)
                    {
                        return string.Concat(new object[]
                        {
                        this.remarks,
                        " ([",
                        text,
                        "]:",
                        this.server_port,
                        ")"
                        });
                    }
                    return string.Concat(new object[]
                    {
                    this.remarks,
                    " (",
                    text,
                    ":",
                    this.server_port,
                    ")"
                    });
                }
            }
            public Server Clone()
            {
                return new Server
                {
                    server = this.server,
                    server_port = this.server_port,
                    password = this.password,
                    method = this.method,
                    protocol = this.protocol,
                    obfs = this.obfs,
                    obfsparam = this.obfsparam ?? "",
                    remarks_base64 = this.remarks_base64,
                    group = this.group,
                    enable = this.enable,
                    udp_over_tcp = this.udp_over_tcp,
                    id = this.id,
                    protocoldata = this.protocoldata,
                    obfsdata = this.obfsdata
                };
            }
            public Server()
            {
                this.server = "server host";
                this.server_port = 8388;
                this.method = "aes-256-cfb";
                this.protocol = "origin";
                this.protocolparam = "";
                this.obfs = "plain";
                this.obfsparam = "";
                this.password = "0";
                this.remarks_base64 = "";
                this.group = "FreeSSR-public";
                this.udp_over_tcp = false;
                this.enable = true;
                this.latency = Server.LATENCY_PENDING;
                byte[] array = new byte[16];
                Utils.RandBytes(array, array.Length);
                this.id = BitConverter.ToString(array).Replace("-", "");
            }
            public Server(string ssURL, string force_group) : this()
            {
                if (ssURL.StartsWith("ss://", StringComparison.OrdinalIgnoreCase))
                {
                    this.ServerFromSS(ssURL, force_group);
                    return;
                }
                if (ssURL.StartsWith("ssr://", StringComparison.OrdinalIgnoreCase))
                {
                    this.ServerFromSSR(ssURL, force_group);
                    return;
                }
                throw new FormatException();
            }
            public bool isMatchServer(Server server)
            {
                return this.server == server.server && this.server_port == server.server_port && this.server_udp_port == server.server_udp_port && this.method == server.method && this.protocol == server.protocol && this.protocolparam == server.protocolparam && this.obfs == server.obfs && this.obfsparam == server.obfsparam && this.password == server.password && this.udp_over_tcp == server.udp_over_tcp;
            }
            private Dictionary<string, string> ParseParam(string param_str)
            {
                Dictionary<string, string> dictionary = new Dictionary<string, string>();
                string[] array = param_str.Split(new char[]
                {
                '&'
                });
                string[] array2 = array;
                for (int i = 0; i < array2.Length; i++)
                {
                    string text = array2[i];
                    if (text.IndexOf('=') > 0)
                    {
                        int num = text.IndexOf('=');
                        string key = text.Substring(0, num);
                        string value = text.Substring(num + 1);
                        dictionary[key] = value;
                    }
                }
                return dictionary;
            }
            public void ServerFromSSR(string ssrURL, string force_group)
            {
                Match match = Regex.Match(ssrURL, "ssr://([A-Za-z0-9_-]+)", RegexOptions.IgnoreCase);
                if (!match.Success)
                {
                    throw new FormatException();
                }
                string text = Base64.DecodeUrlSafeBase64(match.Groups[1].Value);
                Dictionary<string, string> dictionary = new Dictionary<string, string>();
                int num = text.IndexOf("?");
                if (num > 0)
                {
                    dictionary = this.ParseParam(text.Substring(num + 1));
                    text = text.Substring(0, num);
                }
                if (text.IndexOf("/") >= 0)
                {
                    text = text.Substring(0, text.LastIndexOf("/"));
                }
                Regex regex = new Regex("^(.+):([^:]+):([^:]*):([^:]+):([^:]*):([^:]+)");
                Match match2 = regex.Match(text);
                if (match2 == null || !match2.Success)
                {
                    throw new FormatException();
                }
                this.server = match2.Groups[1].Value;
                this.server_port = int.Parse(match2.Groups[2].Value);
                this.protocol = ((match2.Groups[3].Value.Length == 0) ? "origin" : match2.Groups[3].Value);
                this.protocol = this.protocol.Replace("_compatible", "");
                this.method = match2.Groups[4].Value;
                this.obfs = ((match2.Groups[5].Value.Length == 0) ? "plain" : match2.Groups[5].Value);
                this.obfs = this.obfs.Replace("_compatible", "");
                this.password = Base64.DecodeStandardSSRUrlSafeBase64(match2.Groups[6].Value);
                if (dictionary.ContainsKey("protoparam"))
                {
                    this.protocolparam = Base64.DecodeStandardSSRUrlSafeBase64(dictionary["protoparam"]);
                }
                if (dictionary.ContainsKey("obfsparam"))
                {
                    this.obfsparam = Base64.DecodeStandardSSRUrlSafeBase64(dictionary["obfsparam"]);
                }
                if (dictionary.ContainsKey("remarks"))
                {
                    this.remarks = Base64.DecodeStandardSSRUrlSafeBase64(dictionary["remarks"]);
                }
                if (dictionary.ContainsKey("group"))
                {
                    this.group = Base64.DecodeStandardSSRUrlSafeBase64(dictionary["group"]);
                }
                else
                {
                    this.group = "";
                }
                if (dictionary.ContainsKey("uot"))
                {
                    this.udp_over_tcp = (int.Parse(dictionary["uot"]) > 0);
                }
                if (dictionary.ContainsKey("udpport"))
                {
                    this.server_udp_port = int.Parse(dictionary["udpport"]);
                }
                if (!string.IsNullOrEmpty(force_group))
                {
                    this.group = force_group;
                }
            }
            public void ServerFromSS(string ssURL, string force_group)
            {
                Regex regex = new Regex("^(?i)ss://([A-Za-z0-9+-/=_]+)(#(.+))?", RegexOptions.IgnoreCase);
                Regex regex2 = new Regex("^((?<method>.+):(?<password>.*)@(?<hostname>.+?):(?<port>\\d+?))$", RegexOptions.IgnoreCase);
                Match match = regex.Match(ssURL);
                if (!match.Success)
                {
                    throw new FormatException();
                }
                string value = match.Groups[1].Value;
                match = regex2.Match(Encoding.UTF8.GetString(Convert.FromBase64String(value.PadRight(value.Length + (4 - value.Length % 4) % 4, '='))));
                this.protocol = "origin";
                this.method = match.Groups["method"].Value;
                this.password = match.Groups["password"].Value;
                this.server = match.Groups["hostname"].Value;
                this.server_port = int.Parse(match.Groups["port"].Value);
                if (!string.IsNullOrEmpty(force_group))
                {
                    this.group = force_group;
                    return;
                }
                this.group = "";
            }
            public string GetSSLinkForServer()
            {
                string s = string.Concat(new object[]
                {
                this.method,
                ":",
                this.password,
                "@",
                this.server,
                ":",
                this.server_port
                });
                string str = Convert.ToBase64String(Encoding.UTF8.GetBytes(s)).Replace("=", "");
                return "ss://" + str;
            }
            public string GetSSRLinkForServer()
            {
                string str = string.Concat(new object[]
                {
                this.server,
                ":",
                this.server_port,
                ":",
                this.protocol,
                ":",
                this.method,
                ":",
                this.obfs,
                ":",
                Base64.EncodeUrlSafeBase64(this.password, true)
                });
                string text = "obfsparam=" + Base64.EncodeUrlSafeBase64(this.obfsparam ?? "", true);
                if (!string.IsNullOrEmpty(this.protocolparam))
                {
                    text = text + "&protoparam=" + Base64.EncodeUrlSafeBase64(this.protocolparam, true);
                }
                if (!string.IsNullOrEmpty(this.remarks))
                {
                    text = text + "&remarks=" + Base64.EncodeUrlSafeBase64(this.remarks, true);
                }
                if (!string.IsNullOrEmpty(this.group))
                {
                    text = text + "&group=" + Base64.EncodeUrlSafeBase64(this.group, true);
                }
                if (this.udp_over_tcp)
                {
                    text += "&uot=1";
                }
                if (this.server_udp_port > 0)
                {
                    text = text + "&udpport=" + this.server_udp_port.ToString();
                }
                string str2 = Base64.EncodeUrlSafeBase64(str + "/?" + text, true);
                return "ssr://" + str2;
            }
            public bool isEnable()
            {
                return this.enable;
            }
            public void setEnable(bool enable)
            {
                this.enable = enable;
            }
            public object getObfsData()
            {
                return this.obfsdata;
            }
            public void setObfsData(object data)
            {
                this.obfsdata = data;
            }
            public object getProtocolData()
            {
                return this.protocoldata;
            }
            public void setProtocolData(object data)
            {
                this.protocoldata = data;
            }
            public void tcpingLatency()
            {
                List<double> list = new List<double>();
                TcpClient tcpClient = new TcpClient();
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();
                try
                {
                    Dns.GetHostAddresses(this.server);
                }
                catch (Exception)
                {
                    this.latency = Server.LATENCY_ERROR;
                    return;
                }
                IAsyncResult asyncResult = tcpClient.BeginConnect(this.server, this.server_port, null, null);
                if (asyncResult.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(2.0)))
                {
                    stopwatch.Stop();
                    list.Add(stopwatch.Elapsed.TotalMilliseconds);
                }
                else
                {
                    stopwatch.Stop();
                }
                try
                {
                    tcpClient.Close();
                }
                catch (Exception)
                {
                }
                if (list.Count != 0)
                {
                    this.latency = (int)list.Average();
                    return;
                }
                this.latency = Server.LATENCY_ERROR;
            }
        }

        /// <summary>
        /// SS、SSR订阅内容生成
        /// </summary>
        public static class Subscriber
        {
            /// <summary>
            /// 将多个ssr地址转换为订阅内容
            /// </summary>
            /// <param name="ssrs">ssr地址列表</param>
            /// <returns></returns>
            public static string ToSubscribeStr(IEnumerable<string> ssrs)
            {
                // 多个ssr地址用换行符分割,最后用base64编码
                var str = string.Join("\r\n", ssrs);
                var base64 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(str));
                return base64;
            }

            /// <summary>
            /// 从订阅内容中获取ssr地址列表
            /// </summary>
            /// <param name="subscribeContent">ssr订阅内容</param>
            /// <returns>ssr地址列表</returns>
            public static List<string> FromSubscribeStr(string subscribeContent)
            {
                var str = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(subscribeContent));
                var ssrs = str.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
                    .ToList()
                    .FindAll(m => m.StartsWith("ss", StringComparison.InvariantCultureIgnoreCase));
                return ssrs;
            }
        }

        private static class Base64
        {
            public static string DecodeBase64(string val)
            {
                return Encoding.UTF8.GetString(Base64.DecodeBase64ToBytes(val));
            }
            public static byte[] DecodeBase64ToBytes(string val)
            {
                string s = val.PadRight(val.Length + (4 - val.Length % 4) % 4, '=');
                return Convert.FromBase64String(s);
            }
            public static string EncodeUrlSafeBase64(byte[] val, bool trim)
            {
                if (trim)
                {
                    return Convert.ToBase64String(val).Replace('+', '-').Replace('/', '_').TrimEnd(new char[]
                    {
                    '='
                    });
                }
                return Convert.ToBase64String(val).Replace('+', '-').Replace('/', '_');
            }
            public static byte[] DecodeUrlSafeBase64ToBytes(string val)
            {
                string s = val.Replace('-', '+').Replace('_', '/').PadRight(val.Length + (4 - val.Length % 4) % 4, '=');
                return Convert.FromBase64String(s);
            }
            public static string EncodeUrlSafeBase64(string val, bool trim = true)
            {
                return Base64.EncodeUrlSafeBase64(Encoding.UTF8.GetBytes(val), trim);
            }
            public static string DecodeUrlSafeBase64(string val)
            {
                return Encoding.UTF8.GetString(Base64.DecodeUrlSafeBase64ToBytes(val));
            }
            public static string DecodeStandardSSRUrlSafeBase64(string val)
            {
                return Encoding.UTF8.GetString(Base64.DecodeUrlSafeBase64ToBytes(val));
            }
        }

        private static class ServerName
        {
            public static string HideServerAddr(string addr)
            {
                string result = addr;
                IPAddress iPAddress;
                bool flag = IPAddress.TryParse(addr, out iPAddress);
                if (flag)
                {
                    char separator;
                    if (AddressFamily.InterNetwork == iPAddress.AddressFamily)
                    {
                        separator = '.';
                    }
                    else
                    {
                        separator = ':';
                    }
                    result = ServerName.HideAddr(addr, separator);
                }
                else
                {
                    int num = addr.IndexOf('.', 1);
                    if (num > 0)
                    {
                        result = "*" + addr.Substring(num);
                    }
                }
                return result;
            }
            private static string HideAddr(string addr, char separator)
            {
                string text = "";
                string[] array = addr.Split(new char[]
                {
                separator
                });
                string text2 = array[0];
                string text3 = array[array.Length - 1];
                if (0 < text2.Length)
                {
                    text = text2 + separator.ToString();
                }
                text += "**";
                if (0 < text3.Length)
                {
                    text = text + separator.ToString() + text3;
                }
                return text;
            }
        }

        private static class Utils
        {
            public static void RandBytes(byte[] buf, int length)
            {
                byte[] array = new byte[length];
                RNGCryptoServiceProvider rNGCryptoServiceProvider = new RNGCryptoServiceProvider();
                rNGCryptoServiceProvider.GetBytes(array);
                array.CopyTo(buf, 0);
            }
        }
    }
}

 

  • 3
    点赞
  • 1
    评论
  • 17
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值