Enhancements

Add URL aliasing support to shorten request URL.
Add support for parsing and exporting Snell server in configurations.
Add numbering system to process duplicated node names.
Optimize codes.
This commit is contained in:
Tindy X 2020-04-21 22:29:16 +08:00
parent 4b5e0e1346
commit 52c8eff182
No known key found for this signature in database
GPG Key ID: C6AD413169968D58
10 changed files with 192 additions and 19 deletions

View File

@ -87,6 +87,9 @@ template:
- {key: clash.socks_port, value: 7891}
- {key: clash.allow_lan, value: true}
- {key: clash.log_level, value: info}
aliases:
- {uri: /v, target: /version}
server:
listen: 0.0.0.0

View File

@ -174,6 +174,9 @@ clash.socks_port=7891
clash.allow_lan=true
clash.log_level=info
[aliases]
/v=/version
[server]
;Address to bind on for Web Server
listen=0.0.0.0

View File

@ -31,6 +31,7 @@ bool print_debug_info = false, cfw_child_process = false, append_userinfo = true
std::string access_token;
extern std::string custom_group;
extern int global_log_level;
string_map aliases_map;
//global variables for template
std::string template_path;
@ -541,9 +542,9 @@ void readYAMLConf(YAML::Node &node)
if(node["template"]["globals"].IsSequence())
{
eraseElements(global_vars);
std::string key, value;
for(size_t i = 0; i < node["template"]["globals"].size(); i++)
{
std::string key, value;
node["template"]["globals"][i]["key"] >> key;
node["template"]["globals"][i]["value"] >> value;
global_vars[key] = value;
@ -551,6 +552,18 @@ void readYAMLConf(YAML::Node &node)
}
}
if(node["aliases"].IsSequence())
{
reset_redirect();
for(size_t i = 0; i < node["aliases"].size(); i++)
{
std::string uri, target;
node["aliases"][i]["uri"] >> uri;
node["aliases"][i]["target"] >> target;
append_redirect(uri, target);
}
}
if(node["server"].IsDefined())
{
node["server"]["listen"] >> listen_address;
@ -767,6 +780,16 @@ void readConf()
}
global_vars["managed_config_prefix"] = managed_config_prefix;
if(ini.SectionExist("aliases"))
{
ini.EnterSection("aliases");
string_multimap tempmap;
ini.GetItems(tempmap);
reset_redirect();
for(auto &x : tempmap)
append_redirect(x.first, x.second);
}
ini.EnterSection("server");
ini.GetIfExist("listen", listen_address);
ini.GetIntIfExist("port", listen_port);

View File

@ -18,6 +18,7 @@
typedef std::string::size_type string_size;
typedef std::vector<std::string> string_array;
typedef std::map<std::string, std::string> string_map;
typedef const std::string &refCnstStr;
static const std::string base64_chars =

View File

@ -32,6 +32,7 @@ enum
SPEEDTEST_MESSAGE_FOUNDSS,
SPEEDTEST_MESSAGE_FOUNDSSR,
SPEEDTEST_MESSAGE_FOUNDTROJAN,
SPEEDTEST_MESSAGE_FOUNDSNELL,
SPEEDTEST_MESSAGE_WELCOME,
SPEEDTEST_MESSAGE_FOUNDSUB,
SPEEDTEST_MESSAGE_GOTSERVER,
@ -73,6 +74,7 @@ enum
#define SOCKS_DEFAULT_GROUP "SocksProvider"
#define HTTP_DEFAULT_GROUP "HTTPProvider"
#define TROJAN_DEFAULT_GROUP "TrojanProvider"
#define SNELL_DEFAULT_GROUP "SnellProvider"
void printMsg(int index, nodeInfo *node, bool rpcmode);
void printMsgWithDict(int index, bool rpcmode, std::vector<std::string> dict, std::vector<std::string> trans);

View File

@ -1079,6 +1079,18 @@ void explodeClash(Node yamlnode, const std::string &custom_port, std::vector<nod
node.linkType = SPEEDTEST_MESSAGE_FOUNDTROJAN;
node.proxyStr = trojanConstruct(ps, server, port, password, host, true);
break;
case "snell"_hash:
group = SNELL_DEFAULT_GROUP;
singleproxy["psk"] >> password;
if(singleproxy["obfs-opts"].IsDefined())
{
singleproxy["obfs-opts"]["mode"] >> obfs;
singleproxy["obfs-opts"]["host"] >> host;
}
node.linkType = SPEEDTEST_MESSAGE_FOUNDSNELL;
node.proxyStr = snellConstruct(ps, server, port, password, obfs, host);
break;
default:
continue;
}
@ -1418,6 +1430,33 @@ bool explodeSurge(std::string surge, const std::string &custom_port, std::vector
node.proxyStr = trojanConstruct(remarks, server, port, password, host, true);
break;
case "snell"_hash:
node.linkType = SPEEDTEST_MESSAGE_FOUNDSNELL;
node.group = SNELL_DEFAULT_GROUP;
server = trim(configs[1]);
port = custom_port.empty() ? trim(configs[2]) : custom_port;
for(i = 3; i < configs.size(); i++)
{
vArray = split(configs[i], "=");
if(vArray.size() != 2)
continue;
itemName = trim(vArray[0]);
itemVal = trim(vArray[1]);
switch(hash_(itemName))
{
case "psk"_hash: password = itemVal; break;
case "obfs"_hash: plugin = itemVal; break;
case "obfs-host"_hash: host = itemVal; break;
default: continue;
}
}
if(host.empty() && !isIPv4(server) && !isIPv6(server))
host = server;
node.proxyStr = snellConstruct(remarks, server, port, password, plugin, host);
break;
default:
switch(hash_(remarks))
{

View File

@ -13,6 +13,7 @@ std::string ssConstruct(std::string server, std::string port, std::string passwo
std::string socksConstruct(std::string remarks, std::string server, std::string port, std::string username, std::string password);
std::string httpConstruct(std::string remarks, std::string server, std::string port, std::string username, std::string password, bool tls = false);
std::string trojanConstruct(std::string remarks, std::string server, std::string port, std::string password, std::string host, bool tlssecure);
std::string snellConstruct(std::string remarks, std::string server, std::string port, std::string password, std::string obfs, std::string host);
void explodeVmess(std::string vmess, const std::string &custom_port, nodeInfo &node);
void explodeSSR(std::string ssr, bool ss_libev, bool libev, const std::string &custom_port, nodeInfo &node);
void explodeSS(std::string ss, bool libev, const std::string &custom_port, nodeInfo &node);

View File

@ -251,6 +251,29 @@ std::string trojanConstruct(std::string remarks, std::string server, std::string
return sb.GetString();
}
std::string snellConstruct(std::string remarks, std::string server, std::string port, std::string password, std::string obfs, std::string host)
{
rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
writer.StartObject();
writer.Key("Type");
writer.String("Snell");
writer.Key("Remark");
writer.String(remarks.data());
writer.Key("Hostname");
writer.String(server.data());
writer.Key("Port");
writer.Int(to_int(port));
writer.Key("Password");
writer.String(password.data());
writer.Key("OBFS");
writer.String(obfs.data());
writer.Key("Host");
writer.String(host.data());
writer.EndObject();
return sb.GetString();
}
std::string vmessLinkConstruct(std::string remarks, std::string add, std::string port, std::string type, std::string id, std::string aid, std::string net, std::string path, std::string host, std::string tls)
{
rapidjson::StringBuffer sb;
@ -867,10 +890,15 @@ void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, string_arr
if(ext.append_proxy_type)
x.remarks = "[" + type + "] " + x.remarks;
while(std::count(remarks_list.begin(), remarks_list.end(), x.remarks) > 0)
x.remarks += "$";
remark = x.remarks;
int cnt = 2;
while(std::count(remarks_list.begin(), remarks_list.end(), remark) > 0)
{
remark = x.remarks + " " + std::to_string(cnt);
cnt++;
}
x.remarks = remark;
hostname = GetMember(json, "Hostname");
port = GetMember(json, "Port");
username = GetMember(json, "Username");
@ -1009,6 +1037,19 @@ void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, string_arr
if(ext.skip_cert_verify)
singleproxy["skip-cert-verify"] = true;
break;
case SPEEDTEST_MESSAGE_FOUNDSNELL:
obfs = GetMember(json, "OBFS");
host = GetMember(json, "Host");
singleproxy["type"] = "snell";
singleproxy["psk"] = password;
if(obfs.size())
{
singleproxy["obfs-opts"]["mode"] = obfs;
singleproxy["obfs-opts"]["host"] = host;
}
if(std::all_of(password.begin(), password.end(), ::isdigit) && !password.empty())
singleproxy["password"].SetTag("str");
break;
default:
continue;
}
@ -1173,10 +1214,14 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
x.remarks = "[" + type + "] " + x.remarks;
remark = x.remarks;
while(std::count(remarks_list.begin(), remarks_list.end(), x.remarks) > 0)
x.remarks += "$";
int cnt = 2;
while(std::count(remarks_list.begin(), remarks_list.end(), remark) > 0)
{
remark = x.remarks + " " + std::to_string(cnt);
cnt++;
}
x.remarks = remark;
remark = x.remarks;
hostname = GetMember(json, "Hostname");
port = std::to_string((unsigned short)stoi(GetMember(json, "Port")));
username = GetMember(json, "Username");
@ -1274,6 +1319,13 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
if(ext.skip_cert_verify)
proxy += ", skip-cert-verify=1";
break;
case SPEEDTEST_MESSAGE_FOUNDSNELL:
obfs = GetMember(json, "OBFS");
host = GetMember(json, "Host");
proxy = "snell, " + hostname + ", " + port + ", psk=" + password;
if(obfs.size())
proxy += ", obfs=" + obfs + ", obfs-host=" + host;
break;
default:
continue;
}
@ -1719,10 +1771,14 @@ void netchToQuan(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rules
if(ext.append_proxy_type)
x.remarks = "[" + type + "] " + x.remarks;
while(std::count(remarks_list.begin(), remarks_list.end(), x.remarks) > 0)
x.remarks += "$";
remark = x.remarks;
int cnt = 2;
while(std::count(remarks_list.begin(), remarks_list.end(), remark) > 0)
{
remark = x.remarks + " " + std::to_string(cnt);
cnt++;
}
x.remarks = remark;
hostname = GetMember(json, "Hostname");
port = std::to_string((unsigned short)stoi(GetMember(json, "Port")));
@ -1984,10 +2040,14 @@ void netchToQuanX(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rule
if(ext.append_proxy_type)
x.remarks = "[" + type + "] " + x.remarks;
while(std::count(remarks_list.begin(), remarks_list.end(), x.remarks) > 0)
x.remarks += "$";
remark = x.remarks;
int cnt = 2;
while(std::count(remarks_list.begin(), remarks_list.end(), remark) > 0)
{
remark = x.remarks + " " + std::to_string(cnt);
cnt++;
}
x.remarks = remark;
hostname = GetMember(json, "Hostname");
port = std::to_string((unsigned short)stoi(GetMember(json, "Port")));
@ -2110,6 +2170,16 @@ void netchToQuanX(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rule
continue;
rules_upper_bound -= 2;
break;
case "ssid"_hash:
if(rules_upper_bound < 4)
continue;
proxies = vArray[0] + ",";
proxies += std::accumulate(vArray.begin() + 3, vArray.end(), vArray[2], [](std::string a, std::string b)
{
return std::move(a) + "," + std::move(replace_all_distinct(b, "=", ":"));
});
ini.Set("{NONAME}", vArray[1] + "=" + proxies); //insert order
continue;
default:
continue;
}
@ -2361,10 +2431,16 @@ void netchToMellow(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rul
if(ext.append_proxy_type)
x.remarks = "[" + type + "] " + x.remarks;
remark = x.remarks;
remark = x.remarks;
int cnt = 2;
while(std::count(remarks_list.begin(), remarks_list.end(), remark) > 0)
remark = x.remarks = x.remarks + "$";
{
remark = x.remarks + " " + std::to_string(cnt);
cnt++;
}
x.remarks = remark;
hostname = GetMember(json, "Hostname");
port = std::to_string((unsigned short)stoi(GetMember(json, "Port")));
username = GetMember(json, "Username");
@ -2514,12 +2590,16 @@ std::string netchToLoon(std::vector<nodeInfo> &nodes, std::string &base_conf, st
if(ext.append_proxy_type)
x.remarks = "[" + type + "] " + x.remarks;
remark = x.remarks;
while(std::count(remarks_list.begin(), remarks_list.end(), x.remarks) > 0)
x.remarks += "$";
remark = x.remarks;
int cnt = 2;
while(std::count(remarks_list.begin(), remarks_list.end(), remark) > 0)
{
remark = x.remarks + " " + std::to_string(cnt);
cnt++;
}
x.remarks = remark;
hostname = GetMember(json, "Hostname");
port = std::to_string((unsigned short)stoi(GetMember(json, "Port")));
username = GetMember(json, "Username");

View File

@ -14,6 +14,8 @@ struct listener_args
};
void append_response(std::string method, std::string uri, std::string content_type, response_callback response);
void append_redirect(std::string uri, std::string target);
void reset_redirect();
int start_web_server(void *argv);
int start_web_server_multi(void *argv);
void stop_web_server();

View File

@ -30,6 +30,7 @@ struct responseRoute
};
std::vector<responseRoute> responses;
string_map redirect_map;
static inline void buffer_cleanup(struct evbuffer *eb)
{
@ -68,6 +69,14 @@ static inline int process_request(const char *method_str, std::string uri, std::
}
}
auto iter = redirect_map.find(uri);
if(iter != redirect_map.end())
{
return_data = iter->second;
content_type = "REDIRECT";
return 0;
}
return -1;
}
@ -290,3 +299,13 @@ void append_response(std::string method, std::string uri, std::string content_ty
rr.rc = response;
responses.emplace_back(rr);
}
void append_redirect(std::string uri, std::string target)
{
redirect_map[uri] = target;
}
void reset_redirect()
{
eraseElements(redirect_map);
}