mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-06 13:14:11 +00:00
✨ Add custom SNI for proxy
This commit is contained in:
parent
326d027f6c
commit
337ecc44c3
4 changed files with 39 additions and 13 deletions
|
|
@ -1703,7 +1703,8 @@ export class Inbound extends XrayCommonClass {
|
|||
|
||||
static applyExternalProxyTLSParams(externalProxy, params, security) {
|
||||
if (!externalProxy || security !== 'tls') return;
|
||||
if (externalProxy.dest?.length > 0) params.set("sni", externalProxy.dest);
|
||||
const sni = externalProxy.sni?.length > 0 ? externalProxy.sni : externalProxy.dest;
|
||||
if (sni?.length > 0) params.set("sni", sni);
|
||||
if (externalProxy.fingerprint?.length > 0) params.set("fp", externalProxy.fingerprint);
|
||||
const alpn = Inbound.externalProxyAlpn(externalProxy.alpn);
|
||||
if (alpn.length > 0) params.set("alpn", alpn);
|
||||
|
|
@ -1711,7 +1712,8 @@ export class Inbound extends XrayCommonClass {
|
|||
|
||||
static applyExternalProxyTLSObj(externalProxy, obj, security) {
|
||||
if (!externalProxy || !obj || security !== 'tls') return;
|
||||
if (externalProxy.dest?.length > 0) obj.sni = externalProxy.dest;
|
||||
const sni = externalProxy.sni?.length > 0 ? externalProxy.sni : externalProxy.dest;
|
||||
if (sni?.length > 0) obj.sni = sni;
|
||||
if (externalProxy.fingerprint?.length > 0) obj.fp = externalProxy.fingerprint;
|
||||
const alpn = Inbound.externalProxyAlpn(externalProxy.alpn);
|
||||
if (alpn.length > 0) obj.alpn = alpn;
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ const externalProxy = computed({
|
|||
dest: window.location.hostname,
|
||||
port: inbound.value.port,
|
||||
remark: '',
|
||||
sni: '',
|
||||
fingerprint: '',
|
||||
alpn: [],
|
||||
}];
|
||||
|
|
@ -1685,7 +1686,7 @@ watch(() => inbound.value?.protocol, () => stampAdvancedTextFor('stream'));
|
|||
<a-form-item label="External Proxy">
|
||||
<a-switch v-model:checked="externalProxy" />
|
||||
<a-button v-if="externalProxy" size="small" type="primary" :style="{ marginLeft: '10px' }"
|
||||
@click="inbound.stream.externalProxy.push({ forceTls: 'same', dest: '', port: 443, remark: '', fingerprint: '', alpn: [] })">
|
||||
@click="inbound.stream.externalProxy.push({ forceTls: 'same', dest: '', port: 443, remark: '', sni: '', fingerprint: '', alpn: [] })">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
|
|
@ -1712,11 +1713,12 @@ watch(() => inbound.value?.protocol, () => stampAdvancedTextFor('stream'));
|
|||
</a-input>
|
||||
</a-input-group>
|
||||
<a-input-group v-if="row.forceTls === 'tls'" compact :style="{ marginTop: '6px' }">
|
||||
<a-select v-model:value="row.fingerprint" :style="{ width: '35%' }" placeholder="Fingerprint">
|
||||
<a-input v-model:value="row.sni" :style="{ width: '30%' }" placeholder="SNI (defaults to host)" />
|
||||
<a-select v-model:value="row.fingerprint" :style="{ width: '30%' }" placeholder="Fingerprint">
|
||||
<a-select-option value="">Default</a-select-option>
|
||||
<a-select-option v-for="fp in FINGERPRINTS" :key="fp" :value="fp">{{ fp }}</a-select-option>
|
||||
</a-select>
|
||||
<a-select v-model:value="row.alpn" mode="multiple" :style="{ width: '65%' }" placeholder="ALPN">
|
||||
<a-select v-model:value="row.alpn" mode="multiple" :style="{ width: '40%' }" placeholder="ALPN">
|
||||
<a-select-option v-for="alpn in ALPNS" :key="alpn" :value="alpn">{{ alpn }}</a-select-option>
|
||||
</a-select>
|
||||
</a-input-group>
|
||||
|
|
|
|||
|
|
@ -867,8 +867,8 @@ func applyExternalProxyTLSObj(ep map[string]any, obj map[string]any, security st
|
|||
if security != "tls" {
|
||||
return
|
||||
}
|
||||
if dest, ok := ep["dest"].(string); ok && dest != "" {
|
||||
obj["sni"] = dest
|
||||
if sni, ok := externalProxySNI(ep); ok {
|
||||
obj["sni"] = sni
|
||||
}
|
||||
if fp, ok := ep["fingerprint"].(string); ok && fp != "" {
|
||||
obj["fp"] = fp
|
||||
|
|
@ -882,8 +882,8 @@ func applyExternalProxyTLSParams(ep map[string]any, params map[string]string, se
|
|||
if security != "tls" {
|
||||
return
|
||||
}
|
||||
if dest, ok := ep["dest"].(string); ok && dest != "" {
|
||||
params["sni"] = dest
|
||||
if sni, ok := externalProxySNI(ep); ok {
|
||||
params["sni"] = sni
|
||||
}
|
||||
if fp, ok := ep["fingerprint"].(string); ok && fp != "" {
|
||||
params["fp"] = fp
|
||||
|
|
@ -902,8 +902,8 @@ func applyExternalProxyTLSToStream(ep map[string]any, stream map[string]any, sec
|
|||
tlsSettings = map[string]any{}
|
||||
stream["tlsSettings"] = tlsSettings
|
||||
}
|
||||
if dest, ok := ep["dest"].(string); ok && dest != "" {
|
||||
tlsSettings["serverName"] = dest
|
||||
if sni, ok := externalProxySNI(ep); ok {
|
||||
tlsSettings["serverName"] = sni
|
||||
}
|
||||
if fp, ok := ep["fingerprint"].(string); ok && fp != "" {
|
||||
tlsSettings["fingerprint"] = fp
|
||||
|
|
@ -919,6 +919,16 @@ func applyExternalProxyTLSToStream(ep map[string]any, stream map[string]any, sec
|
|||
}
|
||||
}
|
||||
|
||||
func externalProxySNI(ep map[string]any) (string, bool) {
|
||||
if sni, ok := ep["sni"].(string); ok && sni != "" {
|
||||
return sni, true
|
||||
}
|
||||
if dest, ok := ep["dest"].(string); ok && dest != "" {
|
||||
return dest, true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func externalProxyALPN(value any) (string, bool) {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
|
|
|
|||
|
|
@ -449,14 +449,15 @@ func TestApplyExternalProxyTLSParams_UsesProxyDomainAndOverrides(t *testing.T) {
|
|||
}
|
||||
ep := map[string]any{
|
||||
"dest": "proxy.example.com",
|
||||
"sni": "tls.example.com",
|
||||
"fingerprint": "chrome",
|
||||
"alpn": []any{"h3", "h2"},
|
||||
}
|
||||
|
||||
applyExternalProxyTLSParams(ep, params, "tls")
|
||||
|
||||
if params["sni"] != "proxy.example.com" {
|
||||
t.Fatalf("sni = %q, want proxy.example.com", params["sni"])
|
||||
if params["sni"] != "tls.example.com" {
|
||||
t.Fatalf("sni = %q, want tls.example.com", params["sni"])
|
||||
}
|
||||
if params["fp"] != "chrome" {
|
||||
t.Fatalf("fp = %q, want chrome", params["fp"])
|
||||
|
|
@ -466,6 +467,17 @@ func TestApplyExternalProxyTLSParams_UsesProxyDomainAndOverrides(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestApplyExternalProxyTLSParams_FallsBackToDestSNI(t *testing.T) {
|
||||
params := map[string]string{"security": "tls"}
|
||||
ep := map[string]any{"dest": "proxy.example.com"}
|
||||
|
||||
applyExternalProxyTLSParams(ep, params, "tls")
|
||||
|
||||
if params["sni"] != "proxy.example.com" {
|
||||
t.Fatalf("sni = %q, want proxy.example.com", params["sni"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyExternalProxyTLSParams_DoesNotApplyForNone(t *testing.T) {
|
||||
params := map[string]string{
|
||||
"security": "none",
|
||||
|
|
|
|||
Loading…
Reference in a new issue