mirror of
https://github.com/asdlokj1qpi233/subconverter.git
synced 2025-10-28 12:22:37 +00:00
Add support for WireGuard nodes in Clash, Surge and Loon configs
This commit is contained in:
@@ -444,6 +444,20 @@ void proxyToClash(std::vector<Proxy> &nodes, YAML::Node &yamlnode, const ProxyGr
|
||||
if(std::all_of(x.Password.begin(), x.Password.end(), ::isdigit) && !x.Password.empty())
|
||||
singleproxy["password"].SetTag("str");
|
||||
break;
|
||||
case ProxyType::WireGuard:
|
||||
singleproxy["type"] = "wireguard";
|
||||
singleproxy["public-key"] = x.PublicKey;
|
||||
singleproxy["private-key"] = x.PrivateKey;
|
||||
singleproxy["ip"] = x.SelfIP;
|
||||
if(!x.SelfIPv6.empty())
|
||||
singleproxy["ipv6"] = x.SelfIPv6;
|
||||
if(!x.PreSharedKey.empty())
|
||||
singleproxy["preshared-key"] = x.PreSharedKey;
|
||||
if(!x.DnsServers.empty())
|
||||
singleproxy["dns"] = x.DnsServers;
|
||||
if(x.Mtu > 0)
|
||||
singleproxy["mtu"] = x.Mtu;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
@@ -595,6 +609,24 @@ std::string proxyToClash(std::vector<Proxy> &nodes, const std::string &base_conf
|
||||
return output_content;
|
||||
}
|
||||
|
||||
// peer = (public-key = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=, allowed-ips = "0.0.0.0/0, ::/0", endpoint = engage.cloudflareclient.com:2408, client-id = 139/184/125),(public-key = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=, endpoint = engage.cloudflareclient.com:2408)
|
||||
std::string generatePeer(Proxy &node, bool client_id_as_reserved = false)
|
||||
{
|
||||
std::string result;
|
||||
result += "public-key = " + node.PublicKey;
|
||||
result += ", endpoint = " + node.Hostname + ":" + std::to_string(node.Port);
|
||||
if(!node.AllowedIPs.empty())
|
||||
result += ", allowed-ips = \"" + node.AllowedIPs + "\"";
|
||||
if(!node.ClientId.empty())
|
||||
{
|
||||
if(client_id_as_reserved)
|
||||
result += ", reserved = [" + node.ClientId + "]";
|
||||
else
|
||||
result += ", client-id = " + node.ClientId;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string proxyToSurge(std::vector<Proxy> &nodes, const std::string &base_conf, std::vector<RulesetContent> &ruleset_content_array, const ProxyGroupConfigs &extra_proxy_group, int surge_ver, extra_settings &ext)
|
||||
{
|
||||
INIReader ini;
|
||||
@@ -644,7 +676,7 @@ std::string proxyToSurge(std::vector<Proxy> &nodes, const std::string &base_conf
|
||||
scv.define(x.AllowInsecure);
|
||||
tls13.define(x.TLS13);
|
||||
|
||||
std::string proxy;
|
||||
std::string proxy, section, real_section;
|
||||
string_array args, headers;
|
||||
|
||||
switch(x.Type)
|
||||
@@ -770,6 +802,28 @@ std::string proxyToSurge(std::vector<Proxy> &nodes, const std::string &base_conf
|
||||
if(x.SnellVersion != 0)
|
||||
proxy += ", version=" + std::to_string(x.SnellVersion);
|
||||
break;
|
||||
case ProxyType::WireGuard:
|
||||
if(surge_ver < 4 && surge_ver != -3)
|
||||
continue;
|
||||
section = randomStr(5);
|
||||
real_section = "WireGuard " + section;
|
||||
proxy = "wireguard, section-name=" + section;
|
||||
if(!x.TestUrl.empty())
|
||||
proxy += ", test-url=" + x.TestUrl;
|
||||
ini.set(real_section, "private-key", x.PrivateKey);
|
||||
ini.set(real_section, "self-ip", x.SelfIP);
|
||||
if(!x.SelfIPv6.empty())
|
||||
ini.set(real_section, "self-ip-v6", x.SelfIPv6);
|
||||
if(!x.PreSharedKey.empty())
|
||||
ini.set(real_section, "preshared-key", x.PreSharedKey);
|
||||
if(!x.DnsServers.empty())
|
||||
ini.set(real_section, "dns-server", join(x.DnsServers, ","));
|
||||
if(x.Mtu > 0)
|
||||
ini.set(real_section, "mtu", std::to_string(x.Mtu));
|
||||
if(x.KeepAlive > 0)
|
||||
ini.set(real_section, "keepalive", std::to_string(x.KeepAlive));
|
||||
ini.set(real_section, "peer", "(" + generatePeer(x) + ")");
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
@@ -1866,6 +1920,24 @@ std::string proxyToLoon(std::vector<Proxy> &nodes, const std::string &base_conf,
|
||||
proxy += ",skip-cert-verify=" + std::string(scv.get() ? "true" : "false");
|
||||
}
|
||||
break;
|
||||
case ProxyType::WireGuard:
|
||||
proxy = "wireguard, interface-ip=" + x.SelfIP;
|
||||
if(!x.SelfIPv6.empty())
|
||||
proxy += ", interface-ipv6=" + x.SelfIPv6;
|
||||
proxy += ", private-key=" + x.PrivateKey;
|
||||
for(const auto &y : x.DnsServers)
|
||||
{
|
||||
if(isIPv4(y))
|
||||
proxy += ", dns=" + y;
|
||||
else if(isIPv6(y))
|
||||
proxy += ", dnsv6=" + y;
|
||||
}
|
||||
if(x.Mtu > 0)
|
||||
proxy += ", mtu=" + std::to_string(x.Mtu);
|
||||
if(x.KeepAlive > 0)
|
||||
proxy += ", keepalive=" + std::to_string(x.KeepAlive);
|
||||
proxy += ", peers=[{" + generatePeer(x, true) + "}]";
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
#define PROXY_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "../../utils/tribool.h"
|
||||
|
||||
using String = std::string;
|
||||
using StringArray = std::vector<String>;
|
||||
|
||||
enum ProxyType
|
||||
{
|
||||
@@ -17,7 +19,8 @@ enum ProxyType
|
||||
Snell,
|
||||
HTTP,
|
||||
HTTPS,
|
||||
SOCKS5
|
||||
SOCKS5,
|
||||
WireGuard
|
||||
};
|
||||
|
||||
inline String getProxyTypeName(int type)
|
||||
@@ -84,6 +87,18 @@ struct Proxy
|
||||
|
||||
uint16_t SnellVersion = 0;
|
||||
String ServerName;
|
||||
|
||||
String SelfIP;
|
||||
String SelfIPv6;
|
||||
String PublicKey;
|
||||
String PrivateKey;
|
||||
String PreSharedKey;
|
||||
StringArray DnsServers;
|
||||
uint16_t Mtu = 0;
|
||||
String AllowedIPs = "0.0.0.0/0, ::/0";
|
||||
uint16_t KeepAlive = 0;
|
||||
String TestUrl;
|
||||
String ClientId;
|
||||
};
|
||||
|
||||
#define SS_DEFAULT_GROUP "SSProvider"
|
||||
@@ -93,5 +108,6 @@ struct Proxy
|
||||
#define HTTP_DEFAULT_GROUP "HTTPProvider"
|
||||
#define TROJAN_DEFAULT_GROUP "TrojanProvider"
|
||||
#define SNELL_DEFAULT_GROUP "SnellProvider"
|
||||
#define WG_DEFAULT_GROUP "WireGuardProvider"
|
||||
|
||||
#endif // PROXY_H_INCLUDED
|
||||
|
||||
@@ -115,6 +115,20 @@ void snellConstruct(Proxy &node, const std::string &group, const std::string &re
|
||||
node.SnellVersion = version;
|
||||
}
|
||||
|
||||
void wireguardConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &selfIp, const std::string &selfIpv6, const std::string &privKey, const std::string &pubKey, const std::string &psk, const string_array &dns, const std::string &mtu, const std::string &keepalive, const std::string &testUrl, const std::string &clientId, const tribool &udp) {
|
||||
commonConstruct(node, ProxyType::WireGuard, group, remarks, server, port, udp, tribool(), tribool(), tribool());
|
||||
node.SelfIP = selfIp;
|
||||
node.SelfIPv6 = selfIpv6;
|
||||
node.PrivateKey = privKey;
|
||||
node.PublicKey = pubKey;
|
||||
node.PreSharedKey = psk;
|
||||
node.DnsServers = dns;
|
||||
node.Mtu = to_int(mtu);
|
||||
node.KeepAlive = to_int(keepalive);
|
||||
node.TestUrl = testUrl;
|
||||
node.ClientId = clientId;
|
||||
}
|
||||
|
||||
void explodeVmess(std::string vmess, Proxy &node)
|
||||
{
|
||||
std::string version, ps, add, port, type, id, aid, net, path, host, tls, sni;
|
||||
@@ -953,6 +967,8 @@ void explodeClash(Node yamlnode, std::vector<Proxy> &nodes)
|
||||
std::string plugin, pluginopts, pluginopts_mode, pluginopts_host, pluginopts_mux; //ss
|
||||
std::string protocol, protoparam, obfs, obfsparam; //ssr
|
||||
std::string user; //socks
|
||||
std::string ip, ipv6, private_key, public_key, mtu; //wireguard
|
||||
string_array dns_server;
|
||||
tribool udp, tfo, scv;
|
||||
Node singleproxy;
|
||||
uint32_t index = nodes.size();
|
||||
@@ -1151,6 +1167,18 @@ void explodeClash(Node yamlnode, std::vector<Proxy> &nodes)
|
||||
|
||||
snellConstruct(node, group, ps, server, port, password, obfs, host, to_int(aid, 0), udp, tfo, scv);
|
||||
break;
|
||||
case "wireguard"_hash:
|
||||
group = WG_DEFAULT_GROUP;
|
||||
singleproxy["public-key"] >>= public_key;
|
||||
singleproxy["private-key"] >>= private_key;
|
||||
singleproxy["dns"] >>= dns_server;
|
||||
singleproxy["mtu"] >>= mtu;
|
||||
singleproxy["preshared-key"] >>= password;
|
||||
singleproxy["ip"] >>= ip;
|
||||
singleproxy["ipv6"] >>= ipv6;
|
||||
|
||||
wireguardConstruct(node, group, ps, server, port, ip, ipv6, private_key, public_key, password, dns_server, mtu, "0", "", "", udp);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
@@ -1288,6 +1316,41 @@ void explodeKitsunebi(std::string kit, Proxy &node)
|
||||
vmessConstruct(node, V2RAY_DEFAULT_GROUP, remarks, add, port, type, id, aid, net, cipher, path, host, "", tls, "");
|
||||
}
|
||||
|
||||
// peer = (public-key = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=, allowed-ips = "0.0.0.0/0, ::/0", endpoint = engage.cloudflareclient.com:2408, client-id = 139/184/125),(public-key = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=, endpoint = engage.cloudflareclient.com:2408)
|
||||
void parsePeers(Proxy &node, const std::string &data)
|
||||
{
|
||||
auto peers = regGetAllMatch(data, R"(\((.*?)\))", true);
|
||||
if(peers.empty())
|
||||
return;
|
||||
auto peer = peers[0];
|
||||
auto peerdata = regGetAllMatch(peer, R"(([a-z-]+) ?= ?([^" ),]+|".*?"),? ?)", true);
|
||||
if(peerdata.size() % 2 != 0)
|
||||
return;
|
||||
for(size_t i = 0; i < peerdata.size(); i += 2)
|
||||
{
|
||||
auto key = peerdata[i];
|
||||
auto val = peerdata[i + 1];
|
||||
switch(hash_(key))
|
||||
{
|
||||
case "public-key"_hash:
|
||||
node.PublicKey = val;
|
||||
break;
|
||||
case "endpoint"_hash:
|
||||
node.Hostname = val.substr(0, val.rfind(':'));
|
||||
node.Port = to_int(val.substr(val.rfind(':') + 1));
|
||||
break;
|
||||
case "client-id"_hash:
|
||||
node.ClientId = val;
|
||||
break;
|
||||
case "allowed-ips"_hash:
|
||||
node.AllowedIPs = trimOf(val, '"');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool explodeSurge(std::string surge, std::vector<Proxy> &nodes)
|
||||
{
|
||||
std::multimap<std::string, std::string> proxies;
|
||||
@@ -1303,7 +1366,6 @@ bool explodeSurge(std::string surge, std::vector<Proxy> &nodes)
|
||||
ini.keep_empty_section = false;
|
||||
ini.allow_dup_section_titles = true;
|
||||
ini.set_isolated_items_section("Proxy");
|
||||
ini.include_section("Proxy");
|
||||
ini.add_direct_save_section("Proxy");
|
||||
if(surge.find("[Proxy]") != surge.npos)
|
||||
surge = regReplace(surge, R"(^[\S\s]*?\[)", "[", false);
|
||||
@@ -1322,6 +1384,9 @@ bool explodeSurge(std::string surge, std::vector<Proxy> &nodes)
|
||||
std::string plugin, pluginopts, pluginopts_mode, pluginopts_host, mod_url, mod_md5; //ss
|
||||
std::string id, net, tls, host, edge, path; //v2
|
||||
std::string protocol, protoparam; //ssr
|
||||
std::string section, ip, ipv6, private_key, public_key, mtu, test_url, client_id, peer, keepalive; //wireguard
|
||||
string_array dns_servers;
|
||||
string_multimap wireguard_config;
|
||||
std::string version, aead = "1";
|
||||
std::string itemName, itemVal, config;
|
||||
std::vector<std::string> configs, vArray, headers, header;
|
||||
@@ -1660,6 +1725,65 @@ bool explodeSurge(std::string surge, std::vector<Proxy> &nodes)
|
||||
|
||||
snellConstruct(node, SNELL_DEFAULT_GROUP, remarks, server, port, password, plugin, host, to_int(version, 0), udp, tfo, scv);
|
||||
break;
|
||||
case "wireguard"_hash:
|
||||
for (i = 1; i < configs.size(); i++)
|
||||
{
|
||||
vArray = split(trim(configs[i]), "=");
|
||||
if(vArray.size() != 2)
|
||||
continue;
|
||||
itemName = trim(vArray[0]);
|
||||
itemVal = trim(vArray[1]);
|
||||
switch(hash_(itemName))
|
||||
{
|
||||
case "section-name"_hash:
|
||||
section = itemVal;
|
||||
break;
|
||||
case "test-url"_hash:
|
||||
test_url = itemVal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(section.empty())
|
||||
continue;
|
||||
ini.get_items("WireGuard " + section, wireguard_config);
|
||||
if(wireguard_config.empty())
|
||||
continue;
|
||||
|
||||
for (auto &c : wireguard_config)
|
||||
{
|
||||
itemName = trim(c.first);
|
||||
itemVal = trim(c.second);
|
||||
switch(hash_(itemName))
|
||||
{
|
||||
case "self-ip"_hash:
|
||||
ip = itemVal;
|
||||
break;
|
||||
case "self-ip-v6"_hash:
|
||||
ipv6 = itemVal;
|
||||
break;
|
||||
case "private-key"_hash:
|
||||
private_key = itemVal;
|
||||
break;
|
||||
case "dns-server"_hash:
|
||||
vArray = split(itemVal, ",");
|
||||
for (auto &y : vArray)
|
||||
dns_servers.emplace_back(trim(y));
|
||||
break;
|
||||
case "mtu"_hash:
|
||||
mtu = itemVal;
|
||||
break;
|
||||
case "peer"_hash:
|
||||
peer = itemVal;
|
||||
break;
|
||||
case "keepalive"_hash:
|
||||
keepalive = itemVal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wireguardConstruct(node, WG_DEFAULT_GROUP, remarks, "", "0", ip, ipv6, private_key, "", "", dns_servers, mtu, keepalive, test_url, "", udp);
|
||||
parsePeers(node, peer);
|
||||
break;
|
||||
default:
|
||||
switch(hash_(remarks))
|
||||
{
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
using jp = jpcre2::select<char>;
|
||||
//#endif // USE_STD_REGEX
|
||||
|
||||
#include "regexp.h"
|
||||
|
||||
/*
|
||||
#ifdef USE_STD_REGEX
|
||||
bool regValid(const std::string ®)
|
||||
@@ -164,34 +166,54 @@ bool regValid(const std::string ®)
|
||||
}
|
||||
|
||||
int regGetMatch(const std::string &src, const std::string &match, size_t group_count, ...)
|
||||
{
|
||||
auto result = regGetAllMatch(src, match, false);
|
||||
if(result.empty())
|
||||
return -1;
|
||||
va_list vl;
|
||||
va_start(vl, group_count);
|
||||
size_t index = 0;
|
||||
while(group_count)
|
||||
{
|
||||
std::string* arg = va_arg(vl, std::string*);
|
||||
if(arg != nullptr)
|
||||
*arg = std::move(result[index]);
|
||||
index++;
|
||||
group_count--;
|
||||
if(result.size() <= index)
|
||||
break;
|
||||
}
|
||||
va_end(vl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<std::string> regGetAllMatch(const std::string &src, const std::string &match, bool group_only)
|
||||
{
|
||||
jp::Regex reg;
|
||||
reg.setPattern(match).addModifier("m").addPcre2Option(PCRE2_UTF|PCRE2_ALT_BSUX).compile();
|
||||
jp::VecNum vec_num;
|
||||
jp::RegexMatch rm;
|
||||
size_t count = rm.setRegexObject(®).setSubject(src).setNumberedSubstringVector(&vec_num).setModifier("g").match();
|
||||
std::vector<std::string> result;
|
||||
if(!count)
|
||||
return -1;
|
||||
va_list vl;
|
||||
va_start(vl, group_count);
|
||||
size_t index = 0, match_index = 0;
|
||||
while(group_count)
|
||||
return result;
|
||||
size_t begin = 0;
|
||||
if(group_only)
|
||||
begin = 1;
|
||||
size_t index = begin, match_index = 0;
|
||||
while(true)
|
||||
{
|
||||
std::string* arg = va_arg(vl, std::string*);
|
||||
if(arg != NULL)
|
||||
*arg = std::move(vec_num[match_index][index]);
|
||||
index++;
|
||||
group_count--;
|
||||
if(vec_num.size() <= match_index)
|
||||
break;
|
||||
if(vec_num[match_index].size() <= index)
|
||||
{
|
||||
match_index++;
|
||||
index = 0;
|
||||
index = begin;
|
||||
}
|
||||
if(vec_num.size() <= match_index)
|
||||
break;
|
||||
result.push_back(std::move(vec_num[match_index][index]));
|
||||
index++;
|
||||
}
|
||||
va_end(vl);
|
||||
return 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
//#endif // USE_STD_REGEX
|
||||
|
||||
@@ -8,6 +8,7 @@ bool regFind(const std::string &src, const std::string &match);
|
||||
std::string regReplace(const std::string &src, const std::string &match, const std::string &rep, bool global = true, bool multiline = true);
|
||||
bool regMatch(const std::string &src, const std::string &match);
|
||||
int regGetMatch(const std::string &src, const std::string &match, size_t group_count, ...);
|
||||
std::vector<std::string> regGetAllMatch(const std::string &src, const std::string &match, bool group_only = false);
|
||||
std::string regTrim(const std::string &src);
|
||||
|
||||
#endif // REGEXP_H_INCLUDED
|
||||
|
||||
@@ -354,7 +354,7 @@ bool isStrUTF8(const std::string &data)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string randomStr(const int len)
|
||||
std::string randomStr(int len)
|
||||
{
|
||||
std::string retData;
|
||||
srand(time(NULL));
|
||||
|
||||
@@ -33,7 +33,7 @@ std::string trim(const std::string& str, bool before = true, bool after = true);
|
||||
std::string trimQuote(const std::string &str, bool before = true, bool after = true);
|
||||
void trimSelfOf(std::string &str, char target, bool before = true, bool after = true);
|
||||
std::string trimWhitespace(const std::string &str, bool before = false, bool after = true);
|
||||
std::string randomStr(const int len);
|
||||
std::string randomStr(int len);
|
||||
bool isStrUTF8(const std::string &data);
|
||||
|
||||
void removeUTF8BOM(std::string &data);
|
||||
|
||||
Reference in New Issue
Block a user