public static Profile Get(string profileName)
        {
            Environment.GetEnvironmentVariables();
            var data = Environment.GetEnvironmentVariable(KebabCase2PascalCase(profileName.ToLower()));

            if (String.IsNullOrEmpty(data))
            {
                return(null);
            }

            var profile = new Profile();

            using (var reader = new StringReader(data))
            {
                var yaml = new YamlStream();
                yaml.Load(reader);
                var mapping = (yaml.Documents[0].RootNode as YamlMappingNode).Children;

                profile.Source            = (mapping["source"] as YamlScalarNode).Value;
                profile.Name              = (mapping["name"] as YamlScalarNode).Value;
                profile.Type              = ParseProfileTypeName((mapping["type"] as YamlScalarNode).Value);
                profile.AllowDirectAccess = Yaml.GetTruthFromYamlChildrenNode(yaml.Documents[0].RootNode, "allowDirectAccess");

                YamlNode filtersNode;
                if (!mapping.TryGetValue("filters", out filtersNode) || filtersNode.NodeType != YamlNodeType.Sequence)
                {
                    goto EndReading;
                }

                foreach (var filterNode in (filtersNode as YamlSequenceNode).Children)
                {
                    if (filterNode.NodeType != YamlNodeType.Mapping)
                    {
                        continue;
                    }
                    var filter = FilterFactory.GetFilter(Yaml.GetStringOrDefaultFromYamlChildrenNode(filterNode, "name"));
                    if (filter == null)
                    {
                        continue;
                    }
                    filter.LoadOptions(filterNode);
                    profile.Filters.Add(filter);
                }
            }

EndReading:
            return(profile);
        }
        public Server ParseShadowsocksServer(YamlMappingNode proxy)
        {
            string portString = Yaml.GetStringOrDefaultFromYamlChildrenNode(proxy, "port", "0");
            int    port;

            if (!int.TryParse(portString, out port))
            {
                this.logger.LogError($"Invalid port: {port}.");
                return(null);
            }

            var server = new ShadowsocksServer()
            {
                Port     = port,
                Name     = Yaml.GetStringOrDefaultFromYamlChildrenNode(proxy, "name"),
                Host     = Yaml.GetStringOrDefaultFromYamlChildrenNode(proxy, "server"),
                Password = Yaml.GetStringOrDefaultFromYamlChildrenNode(proxy, "password"),
                Method   = Yaml.GetStringOrDefaultFromYamlChildrenNode(proxy, "cipher"),
                UDPRelay = Yaml.GetTruthFromYamlChildrenNode(proxy, "udp"),
            };

            YamlNode pluginOptionsNode;

            // refer to offical clash to parse plugin options
            // https://github.com/Dreamacro/clash/blob/34338e7107c1868124f8aab2446f6b71c9b0640f/adapters/outbound/shadowsocks.go#L135
            if (proxy.Children.TryGetValue("plugin-opts", out pluginOptionsNode) && pluginOptionsNode.NodeType == YamlNodeType.Mapping)
            {
                switch (Yaml.GetStringOrDefaultFromYamlChildrenNode(proxy, "plugin").ToLower())
                {
                case "obfs":
                    var simpleObfsModeString = Yaml.GetStringOrDefaultFromYamlChildrenNode(pluginOptionsNode, "mode");
                    var simpleObfsOptions    = new SimpleObfsPluginOptions();

                    if (SimpleObfsPluginOptions.TryParseMode(simpleObfsModeString, out SimpleObfsPluginMode simpleObfsMode))
                    {
                        simpleObfsOptions.Mode = simpleObfsMode;
                    }
                    else if (!string.IsNullOrWhiteSpace(simpleObfsModeString))
                    {
                        this.logger.LogError($"Unsupported simple-obfs mode: {simpleObfsModeString}. This server will be ignored.");
                        return(null);
                    }
                    simpleObfsOptions.Host = Yaml.GetStringOrDefaultFromYamlChildrenNode(pluginOptionsNode, "host");

                    server.PluginOptions = simpleObfsOptions;
                    break;

                case "v2ray-plugin":
                    // also refer to official v2ray-plugin to parse v2ray-plugin options
                    // https://github.com/shadowsocks/v2ray-plugin/blob/c7017f45bb1e12cf1e4b739bcb8f42f3eb8b22cd/main.go#L126
                    var v2rayModeString = Yaml.GetStringOrDefaultFromYamlChildrenNode(pluginOptionsNode, "mode");
                    var options         = new V2RayPluginOptions();
                    server.PluginOptions = options;

                    if (V2RayPluginOptions.TryParseMode(v2rayModeString, out V2RayPluginMode v2rayMode))
                    {
                        options.Mode = v2rayMode;
                    }
                    else
                    {
                        this.logger.LogError($"Unsupported v2ray-plugin mode: {v2rayModeString}. This server will be ignored.");
                        return(null);
                    }

                    options.Host                 = Yaml.GetStringOrDefaultFromYamlChildrenNode(pluginOptionsNode, "host");
                    options.Path                 = Yaml.GetStringOrDefaultFromYamlChildrenNode(pluginOptionsNode, "path");
                    options.EnableTLS            = Yaml.GetTruthFromYamlChildrenNode(pluginOptionsNode, "tls");
                    options.SkipCertVerification = Yaml.GetTruthFromYamlChildrenNode(pluginOptionsNode, "skip-cert-verify");
                    options.Headers              = new Dictionary <string, string>();

                    YamlNode headersNode;
                    if (!(pluginOptionsNode as YamlMappingNode).Children.TryGetValue("headers", out headersNode))
                    {
                        break;
                    }
                    if (headersNode.NodeType != YamlNodeType.Mapping)
                    {
                        break;
                    }

                    foreach (var header in (headersNode as YamlMappingNode))
                    {
                        if (header.Value.NodeType != YamlNodeType.Scalar)
                        {
                            continue;
                        }
                        options.Headers.Add((header.Key as YamlScalarNode).Value, (header.Value as YamlScalarNode).Value);
                    }
                    break;
                }
            }

            if (server.PluginOptions == null)
            {
                var simpleObfsModeString = Yaml.GetStringOrDefaultFromYamlChildrenNode(proxy, "obfs");

                if (SimpleObfsPluginOptions.TryParseMode(simpleObfsModeString, out SimpleObfsPluginMode simpleObfsMode))
                {
                    server.PluginOptions = new SimpleObfsPluginOptions()
                    {
                        Mode = simpleObfsMode,
                        Host = Yaml.GetStringOrDefaultFromYamlChildrenNode(proxy, "obfs-host")
                    };
                }
                else if (!string.IsNullOrWhiteSpace(simpleObfsModeString))
                {
                    this.logger.LogError($"Unsupported simple-obfs mode: {simpleObfsModeString}");
                    return(null);
                }
            }

            return(server);
        }
Exemple #3
0
        public static Server ParseShadowsocksServer(YamlMappingNode proxy)
        {
            int port;

            if (!Int32.TryParse(Yaml.GetStringOrDefaultFromYamlChildrenNode(proxy, "port", "0"), out port))
            {
                return(null);
            }

            var server = new ShadowsocksServer()
            {
                Port     = port,
                Name     = Yaml.GetStringOrDefaultFromYamlChildrenNode(proxy, "name"),
                Host     = Yaml.GetStringOrDefaultFromYamlChildrenNode(proxy, "server"),
                Password = Yaml.GetStringOrDefaultFromYamlChildrenNode(proxy, "password"),
                Method   = Yaml.GetStringOrDefaultFromYamlChildrenNode(proxy, "cipher"),
                UDPRelay = Yaml.GetTruthFromYamlChildrenNode(proxy, "udp"),
            };

            YamlNode pluginOptionsNode;

            // refer to offical clash to parse plugin options
            // https://github.com/Dreamacro/clash/blob/34338e7107c1868124f8aab2446f6b71c9b0640f/adapters/outbound/shadowsocks.go#L135
            if (proxy.Children.TryGetValue("plugin-opts", out pluginOptionsNode) && pluginOptionsNode.NodeType == YamlNodeType.Mapping)
            {
                switch (Yaml.GetStringOrDefaultFromYamlChildrenNode(proxy, "plugin"))
                {
                case "obfs":
                    server.PluginType    = PluginType.SimpleObfs;
                    server.PluginOptions = new SimpleObfsPluginOptions()
                    {
                        Mode = Yaml.GetStringOrDefaultFromYamlChildrenNode(pluginOptionsNode, "mode"),
                        Host = Yaml.GetStringOrDefaultFromYamlChildrenNode(pluginOptionsNode, "host"),
                    };
                    break;

                case "v2ray-plugin":
                    // also refer to official v2ray-plugin to parse v2ray-plugin options
                    // https://github.com/shadowsocks/v2ray-plugin/blob/c7017f45bb1e12cf1e4b739bcb8f42f3eb8b22cd/main.go#L126
                    var options = new V2RayPluginOptions();
                    server.PluginType    = PluginType.V2Ray;
                    server.PluginOptions = options;

                    options.Host                 = Yaml.GetStringOrDefaultFromYamlChildrenNode(pluginOptionsNode, "host");
                    options.Mode                 = Yaml.GetStringOrDefaultFromYamlChildrenNode(pluginOptionsNode, "mode");
                    options.Path                 = Yaml.GetStringOrDefaultFromYamlChildrenNode(pluginOptionsNode, "path");
                    options.EnableTLS            = Yaml.GetTruthFromYamlChildrenNode(pluginOptionsNode, "tls");
                    options.SkipCertVerification = Yaml.GetTruthFromYamlChildrenNode(pluginOptionsNode, "skip-cert-verify");
                    options.Headers              = new Dictionary <string, string>();

                    YamlNode headersNode;
                    if (!(pluginOptionsNode as YamlMappingNode).Children.TryGetValue("headers", out headersNode))
                    {
                        break;
                    }
                    if (headersNode.NodeType != YamlNodeType.Mapping)
                    {
                        break;
                    }

                    foreach (var header in (headersNode as YamlMappingNode))
                    {
                        if (header.Value.NodeType != YamlNodeType.Scalar)
                        {
                            continue;
                        }
                        options.Headers.Add((header.Key as YamlScalarNode).Value, (header.Value as YamlScalarNode).Value);
                    }
                    break;
                }
            }


            if (server.PluginType == PluginType.None)
            {
                var obfs     = Yaml.GetStringOrDefaultFromYamlChildrenNode(proxy, "obfs");
                var obfsHost = Yaml.GetStringOrDefaultFromYamlChildrenNode(proxy, "obfs-host");

                if (!String.IsNullOrEmpty(obfs))
                {
                    server.PluginType    = PluginType.SimpleObfs;
                    server.PluginOptions = new SimpleObfsPluginOptions()
                    {
                        Mode = obfs,
                        Host = obfsHost
                    };
                }
            }

            return(server);
        }