Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 27 additions & 10 deletions src/generator/config/subexport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,8 @@ void proxyToClash(std::vector<Proxy> &nodes, YAML::Node &yamlnode, const ProxyGr
singleproxy["type"] = "hysteria2";
if (!x.Ports.empty())
singleproxy["ports"] = x.Ports;
if (!x.Mport.empty())
singleproxy["mport"] = x.Mport;
if (!x.Up.empty())
singleproxy["up"] = x.UpSpeed;
if (!x.Down.empty())
Expand Down Expand Up @@ -612,8 +614,13 @@ void proxyToClash(std::vector<Proxy> &nodes, YAML::Node &yamlnode, const ProxyGr
case ProxyType::VLESS:
singleproxy["type"] = "vless";
singleproxy["tls"] = true;
if (udp)
singleproxy["packet-encoding"] = "xudp";
// Output packet-encoding, xudp, packet-addr only if explicitly set
if (!x.PacketEncoding.empty())
singleproxy["packet-encoding"] = x.PacketEncoding;
if (!x.XUDP.is_undef())
singleproxy["xudp"] = x.XUDP.get();
if (!x.PacketAddr.is_undef())
singleproxy["packet-addr"] = x.PacketAddr.get();
if (!x.UUID.empty())
singleproxy["uuid"] = x.UUID;
if (!x.SNI.empty())
Expand All @@ -633,15 +640,17 @@ void proxyToClash(std::vector<Proxy> &nodes, YAML::Node &yamlnode, const ProxyGr
singleproxy["network"] = x.TransferProtocol;
if(ext.clash_new_field_name)
{
singleproxy["ws-opts"]["path"] = x.Path.empty() ? "/" : x.Path;
if(!x.Path.empty())
singleproxy["ws-opts"]["path"] = x.Path;
if(!x.Host.empty())
singleproxy["ws-opts"]["headers"]["Host"] = x.Host;
if(!x.Edge.empty())
singleproxy["ws-opts"]["headers"]["Edge"] = x.Edge;
}
else
{
singleproxy["ws-path"] = x.Path.empty() ? "/" : x.Path;
if(!x.Path.empty())
singleproxy["ws-path"] = x.Path;
if(!x.Host.empty())
singleproxy["ws-headers"]["Host"] = x.Host;
if(!x.Edge.empty())
Expand All @@ -651,15 +660,17 @@ void proxyToClash(std::vector<Proxy> &nodes, YAML::Node &yamlnode, const ProxyGr
case "http"_hash:
singleproxy["network"] = x.TransferProtocol;
singleproxy["http-opts"]["method"] = "GET";
singleproxy["http-opts"]["path"].push_back(x.Path.empty() ? "/" : x.Path);
if(!x.Path.empty())
singleproxy["http-opts"]["path"].push_back(x.Path);
if(!x.Host.empty())
singleproxy["http-opts"]["headers"]["Host"].push_back(x.Host);
if(!x.Edge.empty())
singleproxy["http-opts"]["headers"]["Edge"].push_back(x.Edge);
break;
case "h2"_hash:
singleproxy["network"] = x.TransferProtocol;
singleproxy["h2-opts"]["path"] = x.Path.empty() ? "/" : x.Path;
if(!x.Path.empty())
singleproxy["h2-opts"]["path"] = x.Path;
if(!x.Host.empty())
singleproxy["h2-opts"]["host"].push_back(x.Host);
break;
Expand All @@ -669,20 +680,25 @@ void proxyToClash(std::vector<Proxy> &nodes, YAML::Node &yamlnode, const ProxyGr
singleproxy["grpc-opts"]["grpc-service-name"] = x.GRPCServiceName;
break;
default:
continue;
break;
}

if (!x.Fingerprint.empty())
singleproxy["fingerprint"] = x.Fingerprint;
if (!x.ClientFingerprint.empty())
singleproxy["client-fingerprint"] = x.ClientFingerprint;
if (x.XTLS == 2) {
singleproxy["flow"] = "xtls-rprx-vision";
} else if (!x.FlowSet.is_undef() && x.FlowSet.get()) {
// Output flow field if it was explicitly set (even if empty)
singleproxy["flow"] = x.Flow;
} else if (!x.Flow.empty()) {
// Fallback for backward compatibility
singleproxy["flow"] = x.Flow;
}
if (!x.PublicKey.empty() && !x.ShortID.empty()) {
singleproxy["reality-opts"]["public-key"] = x.PublicKey;
singleproxy["reality-opts"]["short-id"] = x.ShortID;
singleproxy["client-fingerprint"] = "random";
}
if (!scv.is_undef())
singleproxy["skip-cert-verify"] = scv.get();
Expand All @@ -693,8 +709,9 @@ void proxyToClash(std::vector<Proxy> &nodes, YAML::Node &yamlnode, const ProxyGr

// UDP is not supported yet in clash using snell
// sees in https://dreamacro.github.io/clash/configuration/outbound.html#snell
if(udp && x.Type != ProxyType::Snell)
singleproxy["udp"] = true;
// Output UDP field when explicitly provided (true or false)
if(!x.UDP.is_undef() && x.Type != ProxyType::Snell)
singleproxy["udp"] = x.UDP.get();
if(!tfo.is_undef())
singleproxy["tfo"] = tfo.get();
if(proxy_block)
Expand Down
59 changes: 59 additions & 0 deletions src/parser/config/proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ struct Proxy
tribool AllowInsecure;
tribool TLS13;

// Shadowsocks UDP-over-TCP options
tribool UdpOverTcp;
uint32_t UdpOverTcpVersion = 0;

String UnderlyingProxy;

uint16_t SnellVersion = 0;
Expand All @@ -123,6 +127,7 @@ struct Proxy
String ClientId;

String Ports;
String Mport; // Alternative to Ports for Hysteria2
String Up;
uint32_t UpSpeed;
String Down;
Expand All @@ -134,6 +139,12 @@ struct Proxy
String CaStr;
uint32_t RecvWindowConn;
uint32_t RecvWindow;
// Hysteria2 additional receive window configs
uint64_t InitialStreamReceiveWindow = 0;
uint64_t MaxStreamReceiveWindow = 0;
uint64_t InitialConnectionReceiveWindow = 0;
uint64_t MaxConnectionReceiveWindow = 0;
uint32_t UdpMTU = 0;
tribool DisableMtuDiscovery;
uint32_t HopInterval;
StringArray Alpn;
Expand All @@ -149,6 +160,7 @@ struct Proxy
String UdpRelayMode;
String CongestionController;
uint32_t MaxUdpRelayPacketSize;
uint32_t MaxDatagramFrameSize = 0; // TUIC
tribool FastOpen;
uint32_t MaxOpenStreams;

Expand All @@ -157,10 +169,57 @@ struct Proxy
uint32_t MinIdleSession;

String Flow;
tribool FlowSet; // Flag to indicate if Flow field was explicitly set (even if empty)
uint32_t XTLS;
String PacketEncoding;
tribool PacketAddr;
tribool GlobalPadding;
tribool AuthenticatedLength;
tribool XUDP;
String ShortID;

// New parameters from mihomo
String IpVersion; // ip-version: ipv4/ipv6/dual/ipv4-prefer/ipv6-prefer
String ClientFingerprint; // client-fingerprint: chrome/firefox/safari/ios/random/none

// ECH (Encrypted Client Hello) options
tribool EchEnable;
String EchConfig;

// SMUX (multiplexing) options for Shadowsocks
tribool SmuxEnabled;
String SmuxProtocol; // smux/yamux/h2mux
uint32_t SmuxMaxConnections;
uint32_t SmuxMinStreams;
uint32_t SmuxMaxStreams;
tribool SmuxPadding;
tribool SmuxStatistic;
tribool SmuxOnlyTcp;

// mTLS options
String Certificate; // Certificate for mTLS
String PrivateKeyPem; // Private key for mTLS

// VLESS encryption
String VlessEncryption; // mlkem768x25519plus.native/xorpub/random.1rtt/0rtt

// WebSocket additional options
uint32_t WsMaxEarlyData;
String WsEarlyDataHeaderName;
tribool V2rayHttpUpgrade;
tribool V2rayHttpUpgradeFastOpen;

// HTTP options for VLESS
String HttpMethod;
StringArray HttpPath;

// Hysteria2 additional options
tribool HopIntervalTribool; // Already have HopInterval as uint32_t, adding tribool version for better support

// Trojan SS options
String TrojanSsMethod;
String TrojanSsPassword;

};

#define SS_DEFAULT_GROUP "SSProvider"
Expand Down
Loading