mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-02-13 13:57:59 +00:00
inbound : finalmask
This commit is contained in:
parent
c59f54bb0e
commit
3af6497577
6 changed files with 201 additions and 86 deletions
|
|
@ -319,14 +319,12 @@ TcpStreamSettings.TcpResponse = class extends XrayCommonClass {
|
|||
class KcpStreamSettings extends XrayCommonClass {
|
||||
constructor(
|
||||
mtu = 1350,
|
||||
tti = 50,
|
||||
tti = 20,
|
||||
uplinkCapacity = 5,
|
||||
downlinkCapacity = 20,
|
||||
congestion = false,
|
||||
readBufferSize = 2,
|
||||
writeBufferSize = 2,
|
||||
type = 'none',
|
||||
seed = RandomUtil.randomSeq(10),
|
||||
readBufferSize = 1,
|
||||
writeBufferSize = 1,
|
||||
) {
|
||||
super();
|
||||
this.mtu = mtu;
|
||||
|
|
@ -336,8 +334,6 @@ class KcpStreamSettings extends XrayCommonClass {
|
|||
this.congestion = congestion;
|
||||
this.readBuffer = readBufferSize;
|
||||
this.writeBuffer = writeBufferSize;
|
||||
this.type = type;
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
static fromJson(json = {}) {
|
||||
|
|
@ -349,8 +345,6 @@ class KcpStreamSettings extends XrayCommonClass {
|
|||
json.congestion,
|
||||
json.readBufferSize,
|
||||
json.writeBufferSize,
|
||||
ObjectUtil.isEmpty(json.header) ? 'none' : json.header.type,
|
||||
json.seed,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -363,10 +357,6 @@ class KcpStreamSettings extends XrayCommonClass {
|
|||
congestion: this.congestion,
|
||||
readBufferSize: this.readBuffer,
|
||||
writeBufferSize: this.writeBuffer,
|
||||
header: {
|
||||
type: this.type,
|
||||
},
|
||||
seed: this.seed,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -929,6 +919,51 @@ class SockoptStreamSettings extends XrayCommonClass {
|
|||
}
|
||||
}
|
||||
|
||||
class FinalMask extends XrayCommonClass {
|
||||
constructor(type = 'salamander', settings = {}) {
|
||||
super();
|
||||
this.type = type;
|
||||
this.settings = this._getDefaultSettings(type, settings);
|
||||
}
|
||||
|
||||
_getDefaultSettings(type, settings = {}) {
|
||||
switch (type) {
|
||||
case 'salamander':
|
||||
case 'mkcp-aes128gcm':
|
||||
return { password: settings.password || '' };
|
||||
case 'header-dns':
|
||||
case 'xdns':
|
||||
return { domain: settings.domain || '' };
|
||||
case 'mkcp-original':
|
||||
case 'header-dtls':
|
||||
case 'header-srtp':
|
||||
case 'header-utp':
|
||||
case 'header-wechat':
|
||||
case 'header-wireguard':
|
||||
return {};
|
||||
default:
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
|
||||
static fromJson(json = {}) {
|
||||
return new FinalMask(
|
||||
json.type || 'salamander',
|
||||
json.settings || {}
|
||||
);
|
||||
}
|
||||
|
||||
toJson() {
|
||||
const result = {
|
||||
type: this.type
|
||||
};
|
||||
if (this.settings && Object.keys(this.settings).length > 0) {
|
||||
result.settings = this.settings;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
class StreamSettings extends XrayCommonClass {
|
||||
constructor(network = 'tcp',
|
||||
security = 'none',
|
||||
|
|
@ -941,6 +976,7 @@ class StreamSettings extends XrayCommonClass {
|
|||
grpcSettings = new GrpcStreamSettings(),
|
||||
httpupgradeSettings = new HTTPUpgradeStreamSettings(),
|
||||
xhttpSettings = new xHTTPStreamSettings(),
|
||||
finalmask = { udp: [] },
|
||||
sockopt = undefined,
|
||||
) {
|
||||
super();
|
||||
|
|
@ -955,9 +991,23 @@ class StreamSettings extends XrayCommonClass {
|
|||
this.grpc = grpcSettings;
|
||||
this.httpupgrade = httpupgradeSettings;
|
||||
this.xhttp = xhttpSettings;
|
||||
this.finalmask = finalmask;
|
||||
this.sockopt = sockopt;
|
||||
}
|
||||
|
||||
addUdpMask(type = 'salamander') {
|
||||
if (!this.finalmask.udp) {
|
||||
this.finalmask.udp = [];
|
||||
}
|
||||
this.finalmask.udp.push(new FinalMask(type));
|
||||
}
|
||||
|
||||
delUdpMask(index) {
|
||||
if (this.finalmask.udp) {
|
||||
this.finalmask.udp.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
get isTls() {
|
||||
return this.security === "tls";
|
||||
}
|
||||
|
|
@ -992,6 +1042,14 @@ class StreamSettings extends XrayCommonClass {
|
|||
}
|
||||
|
||||
static fromJson(json = {}) {
|
||||
let finalmask = { udp: [] };
|
||||
if (json.finalmask) {
|
||||
if (Array.isArray(json.finalmask)) {
|
||||
finalmask.udp = json.finalmask.map(mask => FinalMask.fromJson(mask));
|
||||
} else if (json.finalmask.udp) {
|
||||
finalmask.udp = json.finalmask.udp.map(mask => FinalMask.fromJson(mask));
|
||||
}
|
||||
}
|
||||
return new StreamSettings(
|
||||
json.network,
|
||||
json.security,
|
||||
|
|
@ -1004,6 +1062,7 @@ class StreamSettings extends XrayCommonClass {
|
|||
GrpcStreamSettings.fromJson(json.grpcSettings),
|
||||
HTTPUpgradeStreamSettings.fromJson(json.httpupgradeSettings),
|
||||
xHTTPStreamSettings.fromJson(json.xhttpSettings),
|
||||
finalmask,
|
||||
SockoptStreamSettings.fromJson(json.sockopt),
|
||||
);
|
||||
}
|
||||
|
|
@ -1022,6 +1081,9 @@ class StreamSettings extends XrayCommonClass {
|
|||
grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined,
|
||||
httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined,
|
||||
xhttpSettings: network === 'xhttp' ? this.xhttp.toJson() : undefined,
|
||||
finalmask: (this.finalmask.udp && this.finalmask.udp.length > 0) ? {
|
||||
udp: this.finalmask.udp.map(mask => mask.toJson())
|
||||
} : undefined,
|
||||
sockopt: this.sockopt != undefined ? this.sockopt.toJson() : undefined,
|
||||
};
|
||||
}
|
||||
|
|
@ -1947,7 +2009,9 @@ Inbound.VLESSSettings = class extends Inbound.Settings {
|
|||
json.selectedAuth = this.selectedAuth;
|
||||
}
|
||||
|
||||
if (this.testseed && this.testseed.length >= 4) {
|
||||
// Only include testseed if at least one client has a flow set
|
||||
const hasFlow = this.vlesses && this.vlesses.some(vless => vless.flow && vless.flow !== '');
|
||||
if (hasFlow && this.testseed && this.testseed.length >= 4) {
|
||||
json.testseed = this.testseed;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -166,14 +166,12 @@ class TcpStreamSettings extends CommonClass {
|
|||
class KcpStreamSettings extends CommonClass {
|
||||
constructor(
|
||||
mtu = 1350,
|
||||
tti = 50,
|
||||
tti = 20,
|
||||
uplinkCapacity = 5,
|
||||
downlinkCapacity = 20,
|
||||
congestion = false,
|
||||
readBufferSize = 2,
|
||||
writeBufferSize = 2,
|
||||
type = 'none',
|
||||
seed = '',
|
||||
readBufferSize = 1,
|
||||
writeBufferSize = 1,
|
||||
) {
|
||||
super();
|
||||
this.mtu = mtu;
|
||||
|
|
@ -183,8 +181,6 @@ class KcpStreamSettings extends CommonClass {
|
|||
this.congestion = congestion;
|
||||
this.readBuffer = readBufferSize;
|
||||
this.writeBuffer = writeBufferSize;
|
||||
this.type = type;
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
static fromJson(json = {}) {
|
||||
|
|
@ -196,8 +192,6 @@ class KcpStreamSettings extends CommonClass {
|
|||
json.congestion,
|
||||
json.readBufferSize,
|
||||
json.writeBufferSize,
|
||||
ObjectUtil.isEmpty(json.header) ? 'none' : json.header.type,
|
||||
json.seed,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -210,10 +204,6 @@ class KcpStreamSettings extends CommonClass {
|
|||
congestion: this.congestion,
|
||||
readBufferSize: this.readBuffer,
|
||||
writeBufferSize: this.writeBuffer,
|
||||
header: {
|
||||
type: this.type,
|
||||
},
|
||||
seed: this.seed,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -407,21 +407,6 @@
|
|||
|
||||
<!-- kcp -->
|
||||
<template v-if="outbound.stream.network === 'kcp'">
|
||||
<a-form-item label='{{ i18n "camouflage" }}'>
|
||||
<a-select v-model="outbound.stream.kcp.type"
|
||||
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||
<a-select-option value="none">None</a-select-option>
|
||||
<a-select-option value="srtp">SRTP</a-select-option>
|
||||
<a-select-option value="utp">uTP</a-select-option>
|
||||
<a-select-option value="wechat-video">WeChat</a-select-option>
|
||||
<a-select-option value="dtls">DTLS 1.2</a-select-option>
|
||||
<a-select-option value="wireguard">WireGuard</a-select-option>
|
||||
<a-select-option value="dns">DNS</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label='{{ i18n "password" }}'>
|
||||
<a-input v-model="outbound.stream.kcp.seed"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label='MTU'>
|
||||
<a-input-number v-model.number="outbound.stream.kcp.mtu"
|
||||
min="0"></a-input-number>
|
||||
|
|
@ -607,7 +592,7 @@
|
|||
<template v-if="outbound.canEnableStream()">
|
||||
<a-form-item label="UDP Masks">
|
||||
<a-button icon="plus" type="primary" size="small"
|
||||
@click="outbound.stream.addUdpMask(outbound.protocol === Protocols.Hysteria ? 'salamander' : 'mkcp-aes128gcm')"></a-button>
|
||||
@click="outbound.stream.addUdpMask(outbound.protocol === Protocols.Hysteria ? 'salamander' : (outbound.stream.network === 'kcp' ? 'mkcp-aes128gcm' : 'xdns'))"></a-button>
|
||||
</a-form-item>
|
||||
<template
|
||||
v-if="outbound.stream.finalmask.udp && outbound.stream.finalmask.udp.length > 0">
|
||||
|
|
@ -623,25 +608,39 @@
|
|||
<a-select v-model="mask.type"
|
||||
@change="(type) => mask.settings = mask._getDefaultSettings(type, {})"
|
||||
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||
<a-select-option v-if="outbound.protocol === Protocols.Hysteria" value="salamander">
|
||||
<!-- Salamander for Hysteria2 only -->
|
||||
<a-select-option v-if="outbound.protocol === Protocols.Hysteria"
|
||||
value="salamander">
|
||||
Salamander (Hysteria2)</a-select-option>
|
||||
<a-select-option value="mkcp-aes128gcm">
|
||||
<!-- mKCP-specific masks -->
|
||||
<a-select-option v-if="outbound.stream.network === 'kcp'"
|
||||
value="mkcp-aes128gcm">
|
||||
mKCP AES-128-GCM</a-select-option>
|
||||
<a-select-option value="header-dns">
|
||||
<a-select-option v-if="outbound.stream.network === 'kcp'"
|
||||
value="header-dns">
|
||||
Header DNS</a-select-option>
|
||||
<a-select-option value="header-dtls">
|
||||
<a-select-option v-if="outbound.stream.network === 'kcp'"
|
||||
value="header-dtls">
|
||||
Header DTLS 1.2</a-select-option>
|
||||
<a-select-option value="header-srtp">
|
||||
<a-select-option v-if="outbound.stream.network === 'kcp'"
|
||||
value="header-srtp">
|
||||
Header SRTP</a-select-option>
|
||||
<a-select-option value="header-utp">
|
||||
<a-select-option v-if="outbound.stream.network === 'kcp'"
|
||||
value="header-utp">
|
||||
Header uTP</a-select-option>
|
||||
<a-select-option value="header-wechat">
|
||||
<a-select-option v-if="outbound.stream.network === 'kcp'"
|
||||
value="header-wechat">
|
||||
Header WeChat Video</a-select-option>
|
||||
<a-select-option value="header-wireguard">
|
||||
<a-select-option v-if="outbound.stream.network === 'kcp'"
|
||||
value="header-wireguard">
|
||||
Header WireGuard</a-select-option>
|
||||
<a-select-option value="mkcp-original">
|
||||
<a-select-option v-if="outbound.stream.network === 'kcp'"
|
||||
value="mkcp-original">
|
||||
mKCP Original</a-select-option>
|
||||
<a-select-option value="xdns">
|
||||
<!-- xDNS for TCP/WS/HTTPUpgrade/XHTTP -->
|
||||
<a-select-option
|
||||
v-if="['tcp', 'ws', 'httpupgrade', 'xhttp'].includes(outbound.stream.network)"
|
||||
value="xdns">
|
||||
xDNS (Experimental)</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
|
|
|
|||
70
web/html/form/stream/stream_finalmask.html
Normal file
70
web/html/form/stream/stream_finalmask.html
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
{{define "form/streamFinalMask"}}
|
||||
<a-divider :style="{ margin: '5px 0 0' }"></a-divider>
|
||||
<a-form :colon="false" :label-col="{ md: {span:8} }"
|
||||
:wrapper-col="{ md: {span:14} }">
|
||||
<a-form-item label="UDP Masks">
|
||||
<a-button icon="plus" type="primary" size="small"
|
||||
@click="inbound.stream.addUdpMask(inbound.stream.network === 'kcp' ? 'mkcp-aes128gcm' : 'xdns')"></a-button>
|
||||
</a-form-item>
|
||||
<template
|
||||
v-if="inbound.stream.finalmask.udp && inbound.stream.finalmask.udp.length > 0">
|
||||
<a-form v-for="(mask, index) in inbound.stream.finalmask.udp"
|
||||
:key="index" :colon="false"
|
||||
:label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }">
|
||||
<a-divider :style="{ margin: '0' }"> UDP Mask [[ index + 1 ]]
|
||||
<a-icon type="delete"
|
||||
@click="() => inbound.stream.delUdpMask(index)"
|
||||
:style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer' }"></a-icon>
|
||||
</a-divider>
|
||||
<a-form-item label='Type'>
|
||||
<a-select v-model="mask.type"
|
||||
@change="(type) => mask.settings = mask._getDefaultSettings(type, {})"
|
||||
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||
<!-- mKCP-specific masks -->
|
||||
<a-select-option v-if="inbound.stream.network === 'kcp'"
|
||||
value="mkcp-aes128gcm">
|
||||
mKCP AES-128-GCM</a-select-option>
|
||||
<a-select-option v-if="inbound.stream.network === 'kcp'"
|
||||
value="header-dns">
|
||||
Header DNS</a-select-option>
|
||||
<a-select-option v-if="inbound.stream.network === 'kcp'"
|
||||
value="header-dtls">
|
||||
Header DTLS 1.2</a-select-option>
|
||||
<a-select-option v-if="inbound.stream.network === 'kcp'"
|
||||
value="header-srtp">
|
||||
Header SRTP</a-select-option>
|
||||
<a-select-option v-if="inbound.stream.network === 'kcp'"
|
||||
value="header-utp">
|
||||
Header uTP</a-select-option>
|
||||
<a-select-option v-if="inbound.stream.network === 'kcp'"
|
||||
value="header-wechat">
|
||||
Header WeChat Video</a-select-option>
|
||||
<a-select-option v-if="inbound.stream.network === 'kcp'"
|
||||
value="header-wireguard">
|
||||
Header WireGuard</a-select-option>
|
||||
<a-select-option v-if="inbound.stream.network === 'kcp'"
|
||||
value="mkcp-original">
|
||||
mKCP Original</a-select-option>
|
||||
<!-- xDNS for TCP/WS/HTTPUpgrade/XHTTP -->
|
||||
<a-select-option
|
||||
v-if="['tcp', 'ws', 'httpupgrade', 'xhttp'].includes(inbound.stream.network)"
|
||||
value="xdns">
|
||||
xDNS (Experimental)</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<!-- Settings for password-based masks -->
|
||||
<a-form-item label='Password'
|
||||
v-if="['mkcp-aes128gcm'].includes(mask.type)">
|
||||
<a-input v-model.trim="mask.settings.password"
|
||||
placeholder="Obfuscation password"></a-input>
|
||||
</a-form-item>
|
||||
<!-- Settings for domain-based masks -->
|
||||
<a-form-item label='Domain'
|
||||
v-if="['header-dns', 'xdns'].includes(mask.type)">
|
||||
<a-input v-model.trim="mask.settings.domain"
|
||||
placeholder="e.g., www.example.com"></a-input>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</template>
|
||||
</a-form>
|
||||
{{end}}
|
||||
|
|
@ -1,48 +1,32 @@
|
|||
{{define "form/streamKCP"}}
|
||||
<a-form :colon="false" :label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }">
|
||||
<a-form-item label='{{ i18n "camouflage" }}'>
|
||||
<a-select v-model="inbound.stream.kcp.type" :style="{ width: '50%' }" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||
<a-select-option value="none">None</a-select-option>
|
||||
<a-select-option value="srtp">SRTP</a-select-option>
|
||||
<a-select-option value="utp">uTP</a-select-option>
|
||||
<a-select-option value="wechat-video">WeChat</a-select-option>
|
||||
<a-select-option value="dtls">DTLS 1.2</a-select-option>
|
||||
<a-select-option value="wireguard">WireGuard</a-select-option>
|
||||
<a-select-option value="dns">DNS</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<template slot="label">
|
||||
<a-tooltip>
|
||||
<template slot="title">
|
||||
<span>{{ i18n "reset" }}</span>
|
||||
</template>
|
||||
{{ i18n "password" }}
|
||||
<a-icon @click="inbound.stream.kcp.seed = RandomUtil.randomSeq(10)"type="sync"> </a-icon>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<a-input v-model.trim="inbound.stream.kcp.seed"></a-input>
|
||||
</a-form-item>
|
||||
<a-form :colon="false" :label-col="{ md: {span:8} }"
|
||||
:wrapper-col="{ md: {span:14} }">
|
||||
<a-form-item label='MTU'>
|
||||
<a-input-number v-model.number="inbound.stream.kcp.mtu" :min="576" :max="1460"></a-input-number>
|
||||
<a-input-number v-model.number="inbound.stream.kcp.mtu" :min="576"
|
||||
:max="1460"></a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item label='TTI (ms)'>
|
||||
<a-input-number v-model.number="inbound.stream.kcp.tti" :min="10" :max="100"></a-input-number>
|
||||
<a-input-number v-model.number="inbound.stream.kcp.tti" :min="10"
|
||||
:max="100"></a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item label='Uplink (MB/s)'>
|
||||
<a-input-number v-model.number="inbound.stream.kcp.upCap" :min="0"></a-input-number>
|
||||
</a-form-item>
|
||||
<a-input-number v-model.number="inbound.stream.kcp.upCap"
|
||||
:min="0"></a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item label='Downlink (MB/s)'>
|
||||
<a-input-number v-model.number="inbound.stream.kcp.downCap" :min="0"></a-input-number>
|
||||
<a-input-number v-model.number="inbound.stream.kcp.downCap"
|
||||
:min="0"></a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item label='Congestion'>
|
||||
<a-switch v-model="inbound.stream.kcp.congestion"></a-switch>
|
||||
</a-form-item>
|
||||
<a-form-item label='Read Buffer (MB)'>
|
||||
<a-input-number v-model.number="inbound.stream.kcp.readBuffer" :min="0"></a-input-number>
|
||||
<a-input-number v-model.number="inbound.stream.kcp.readBuffer"
|
||||
:min="0"></a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item label='Write Buffer (MB)'>
|
||||
<a-input-number v-model.number="inbound.stream.kcp.writeBuffer" :min="0"></a-input-number>
|
||||
<a-input-number v-model.number="inbound.stream.kcp.writeBuffer"
|
||||
:min="0"></a-input-number>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
{{end}}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{{define "form/streamSettings"}}
|
||||
<!-- select stream network -->
|
||||
<a-form :colon="false" :label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }">
|
||||
<a-form :colon="false" :label-col="{ md: {span:8} }"
|
||||
:wrapper-col="{ md: {span:14} }">
|
||||
<a-form-item label='{{ i18n "transmission" }}'>
|
||||
<a-select v-model="inbound.stream.network" :style="{ width: '75%' }" @change="streamNetworkChange"
|
||||
<a-select v-model="inbound.stream.network" :style="{ width: '75%' }"
|
||||
@change="streamNetworkChange"
|
||||
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||
<a-select-option value="tcp">TCP (RAW)</a-select-option>
|
||||
<a-select-option value="kcp">mKCP</a-select-option>
|
||||
|
|
@ -48,4 +50,10 @@
|
|||
<template>
|
||||
{{template "form/streamSockopt"}}
|
||||
</template>
|
||||
|
||||
<!-- finalmask - only for TCP, WS, HTTPUpgrade, XHTTP, mKCP -->
|
||||
<template
|
||||
v-if="['tcp', 'ws', 'httpupgrade', 'xhttp', 'kcp'].includes(inbound.stream.network)">
|
||||
{{template "form/streamFinalMask"}}
|
||||
</template>
|
||||
{{end}}
|
||||
|
|
|
|||
Loading…
Reference in a new issue