Compare commits

..

7 Commits

Author SHA1 Message Date
mhsanaei
b6bb0b1787 v2.3.4 2024-05-24 11:12:49 +02:00
mhsanaei
c0b5d5506f View Current Settings - show webBasePath 2024-05-24 11:08:16 +02:00
mhsanaei
a2f6d3b8dc new - (TLS) Session Resumption 2024-05-24 10:17:20 +02:00
mhsanaei
80cd793154 new - sockopt : all features #2293 2024-05-24 09:57:14 +02:00
Ahmad Thoriq Najahi
d070a82b3d feat: Enhance host extraction from headers (#2292)
- Refactor SUBController subs and subJsons methods to extract host from X-Forwarded-Host header, falling back to X-Real-IP header and then to the request host if unavailable.
- Update html function to extract host from X-Forwarded-Host header, falling back to X-Real-IP header and then to the request host if unavailable.
- Update DomainValidatorMiddleware to first attempt to extract host from X-Forwarded-Host header, falling back to X-Real-IP header and then to the request host.

Fixes: #2284

Signed-off-by: Ahmad Thoriq Najahi <najahi@zephyrus.id>
2024-05-23 23:51:19 +02:00
mhsanaei
5ec16301a6 Add X-Real-IP Support for Client IP (login page) 2024-05-23 15:16:13 +02:00
mhsanaei
07245d614a Upgrade - Xray Core v1.8.13 2024-05-23 10:52:25 +02:00
15 changed files with 207 additions and 42 deletions

View File

@@ -83,7 +83,7 @@ jobs:
cd x-ui/bin cd x-ui/bin
# Download dependencies # Download dependencies
Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v1.8.11/" Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v1.8.13/"
if [ "${{ matrix.platform }}" == "amd64" ]; then if [ "${{ matrix.platform }}" == "amd64" ]; then
wget ${Xray_URL}Xray-linux-64.zip wget ${Xray_URL}Xray-linux-64.zip
unzip Xray-linux-64.zip unzip Xray-linux-64.zip

View File

@@ -27,7 +27,7 @@ case $1 in
esac esac
mkdir -p build/bin mkdir -p build/bin
cd build/bin cd build/bin
wget "https://github.com/XTLS/Xray-core/releases/download/v1.8.11/Xray-linux-${ARCH}.zip" wget "https://github.com/XTLS/Xray-core/releases/download/v1.8.13/Xray-linux-${ARCH}.zip"
unzip "Xray-linux-${ARCH}.zip" unzip "Xray-linux-${ARCH}.zip"
rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat
mv xray "xray-linux-${FNAME}" mv xray "xray-linux-${FNAME}"

View File

@@ -28,10 +28,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
## Instalar una Versión Personalizada ## Instalar una Versión Personalizada
Para instalar la versión deseada, agrega la versión al final del comando de instalación. Por ejemplo, ver `v2.3.3`: Para instalar la versión deseada, agrega la versión al final del comando de instalación. Por ejemplo, ver `v2.3.4`:
``` ```
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.3 bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.4
``` ```
## Certificado SSL ## Certificado SSL

View File

@@ -28,10 +28,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
## Install Custom Version ## Install Custom Version
To install your desired version, add the version to the end of the installation command. e.g., ver `v2.3.3`: To install your desired version, add the version to the end of the installation command. e.g., ver `v2.3.4`:
``` ```
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.3 bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.4
``` ```
## SSL Certificate ## SSL Certificate

View File

@@ -28,10 +28,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
## 安装指定版本 ## 安装指定版本
要安装所需的版本,请将该版本添加到安装命令的末尾。 e.g., ver `v2.3.3`: 要安装所需的版本,请将该版本添加到安装命令的末尾。 e.g., ver `v2.3.4`:
``` ```
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.3 bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.4
``` ```
## SSL 认证 ## SSL 认证

View File

@@ -1 +1 @@
2.3.3 2.3.4

2
go.mod
View File

@@ -14,7 +14,7 @@ require (
github.com/robfig/cron/v3 v3.0.1 github.com/robfig/cron/v3 v3.0.1
github.com/shirou/gopsutil/v3 v3.24.4 github.com/shirou/gopsutil/v3 v3.24.4
github.com/valyala/fasthttp v1.53.0 github.com/valyala/fasthttp v1.53.0
github.com/xtls/xray-core v1.8.12 github.com/xtls/xray-core v1.8.13
go.uber.org/atomic v1.11.0 go.uber.org/atomic v1.11.0
golang.org/x/text v0.15.0 golang.org/x/text v0.15.0
google.golang.org/grpc v1.64.0 google.golang.org/grpc v1.64.0

4
go.sum
View File

@@ -281,8 +281,8 @@ github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1Y
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/xtls/reality v0.0.0-20240429224917-ecc4401070cc h1:0Nj8T1n7F7+v4vRVroaJIvY6R0vNABLfPH+lzPHRJvI= github.com/xtls/reality v0.0.0-20240429224917-ecc4401070cc h1:0Nj8T1n7F7+v4vRVroaJIvY6R0vNABLfPH+lzPHRJvI=
github.com/xtls/reality v0.0.0-20240429224917-ecc4401070cc/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE= github.com/xtls/reality v0.0.0-20240429224917-ecc4401070cc/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE=
github.com/xtls/xray-core v1.8.12 h1:FSEwQxq9VoMDVIu18Iq0sSnASMQ0naWeWEyZwd4jRNY= github.com/xtls/xray-core v1.8.13 h1:x1wG7iC8xjVnlayGA+S4c7EUobx6Gg0ttSm2SFwLrik=
github.com/xtls/xray-core v1.8.12/go.mod h1:h4A21+wcMIFDAqHzSKTXMZQr3lto6WOTUWodamVi/kM= github.com/xtls/xray-core v1.8.13/go.mod h1:h4A21+wcMIFDAqHzSKTXMZQr3lto6WOTUWodamVi/kM=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=

22
main.go
View File

@@ -125,22 +125,35 @@ func showSetting(show bool) {
settingService := service.SettingService{} settingService := service.SettingService{}
port, err := settingService.GetPort() port, err := settingService.GetPort()
if err != nil { if err != nil {
fmt.Println("get current port failed,error info:", err) fmt.Println("get current port failed, error info:", err)
} }
webBasePath, err := settingService.GetBasePath()
if err != nil {
fmt.Println("get webBasePath failed, error info:", err)
}
userService := service.UserService{} userService := service.UserService{}
userModel, err := userService.GetFirstUser() userModel, err := userService.GetFirstUser()
if err != nil { if err != nil {
fmt.Println("get current user info failed,error info:", err) fmt.Println("get current user info failed, error info:", err)
} }
username := userModel.Username username := userModel.Username
userpasswd := userModel.Password userpasswd := userModel.Password
if (username == "") || (userpasswd == "") { if username == "" || userpasswd == "" {
fmt.Println("current username or password is empty") fmt.Println("current username or password is empty")
} }
fmt.Println("current panel settings as follows:") fmt.Println("current panel settings as follows:")
fmt.Println("username:", username) fmt.Println("username:", username)
fmt.Println("userpasswd:", userpasswd) fmt.Println("userpasswd:", userpasswd)
fmt.Println("port:", port) fmt.Println("port:", port)
if webBasePath != "" {
fmt.Println("webBasePath:", webBasePath)
} else {
fmt.Println("webBasePath is not set")
}
} }
} }
@@ -220,6 +233,7 @@ func updateSetting(port int, username string, password string) {
fmt.Printf("set port %v success", port) fmt.Printf("set port %v success", port)
} }
} }
if username != "" || password != "" { if username != "" || password != "" {
userService := service.UserService{} userService := service.UserService{}
err := userService.UpdateFirstUser(username, password) err := userService.UpdateFirstUser(username, password)
@@ -288,6 +302,7 @@ func main() {
var port int var port int
var username string var username string
var password string var password string
var webBasePath string
var tgbottoken string var tgbottoken string
var tgbotchatid string var tgbotchatid string
var enabletgbot bool var enabletgbot bool
@@ -301,6 +316,7 @@ func main() {
settingCmd.IntVar(&port, "port", 0, "set panel port") settingCmd.IntVar(&port, "port", 0, "set panel port")
settingCmd.StringVar(&username, "username", "", "set login username") settingCmd.StringVar(&username, "username", "", "set login username")
settingCmd.StringVar(&password, "password", "", "set login password") settingCmd.StringVar(&password, "password", "", "set login password")
settingCmd.StringVar(&webBasePath, "webBasePath", "", "set web base path")
settingCmd.StringVar(&tgbottoken, "tgbottoken", "", "set telegram bot token") settingCmd.StringVar(&tgbottoken, "tgbottoken", "", "set telegram bot token")
settingCmd.StringVar(&tgbotRuntime, "tgbotRuntime", "", "set telegram bot cron time") settingCmd.StringVar(&tgbotRuntime, "tgbotRuntime", "", "set telegram bot cron time")
settingCmd.StringVar(&tgbotchatid, "tgbotchatid", "", "set telegram bot chat id") settingCmd.StringVar(&tgbotchatid, "tgbotchatid", "", "set telegram bot chat id")

View File

@@ -54,7 +54,18 @@ func (a *SUBController) initRouter(g *gin.RouterGroup) {
func (a *SUBController) subs(c *gin.Context) { func (a *SUBController) subs(c *gin.Context) {
subId := c.Param("subid") subId := c.Param("subid")
host, _, _ := net.SplitHostPort(c.Request.Host) host := c.GetHeader("X-Forwarded-Host")
if host == "" {
host = c.GetHeader("X-Real-IP")
}
if host == "" {
var err error
host, _, err = net.SplitHostPort(c.Request.Host)
if err != nil {
host = c.Request.Host
}
}
host = host
subs, header, err := a.subService.GetSubs(subId, host) subs, header, err := a.subService.GetSubs(subId, host)
if err != nil || len(subs) == 0 { if err != nil || len(subs) == 0 {
c.String(400, "Error!") c.String(400, "Error!")
@@ -79,7 +90,18 @@ func (a *SUBController) subs(c *gin.Context) {
func (a *SUBController) subJsons(c *gin.Context) { func (a *SUBController) subJsons(c *gin.Context) {
subId := c.Param("subid") subId := c.Param("subid")
host, _, _ := net.SplitHostPort(c.Request.Host) host := c.GetHeader("X-Forwarded-Host")
if host == "" {
host = c.GetHeader("X-Real-IP")
}
if host == "" {
var err error
host, _, err = net.SplitHostPort(c.Request.Host)
if err != nil {
host = c.Request.Host
}
}
host = host
jsonSub, header, err := a.subJsonService.GetJson(subId, host) jsonSub, header, err := a.subJsonService.GetJson(subId, host)
if err != nil || len(jsonSub) == 0 { if err != nil || len(jsonSub) == 0 {
c.String(400, "Error!") c.String(400, "Error!")

View File

@@ -90,6 +90,25 @@ const USAGE_OPTION = {
ISSUE: "issue", ISSUE: "issue",
}; };
const DOMAIN_STRATEGY_OPTION = {
AS_IS: "AsIs",
USE_IP: "UseIP",
USE_IPV6V4: "UseIPv6v4",
USE_IPV6: "UseIPv6",
USE_IPV4V6: "UseIPv4v6",
USE_IPV4: "UseIPv4",
FORCE_IP: "ForceIP",
FORCE_IPV6V4: "ForceIPv6v4",
FORCE_IPV6: "ForceIPv6",
FORCE_IPV4V6: "ForceIPv4v6",
FORCE_IPV4: "ForceIPv4",
};
const TCP_CONGESTION_OPTION = {
BBR: "bbr",
CUBIC: "cubic",
RENO: "reno",
};
Object.freeze(Protocols); Object.freeze(Protocols);
Object.freeze(SSMethods); Object.freeze(SSMethods);
Object.freeze(XTLS_FLOW_CONTROL); Object.freeze(XTLS_FLOW_CONTROL);
@@ -100,6 +119,8 @@ Object.freeze(UTLS_FINGERPRINT);
Object.freeze(ALPN_OPTION); Object.freeze(ALPN_OPTION);
Object.freeze(SNIFFING_OPTION); Object.freeze(SNIFFING_OPTION);
Object.freeze(USAGE_OPTION); Object.freeze(USAGE_OPTION);
Object.freeze(DOMAIN_STRATEGY_OPTION);
Object.freeze(TCP_CONGESTION_OPTION);
class XrayCommonClass { class XrayCommonClass {
@@ -535,6 +556,7 @@ class TlsStreamSettings extends XrayCommonClass {
cipherSuites = '', cipherSuites = '',
rejectUnknownSni = false, rejectUnknownSni = false,
disableSystemRoot = false, disableSystemRoot = false,
enableSessionResumption = false,
certificates=[new TlsStreamSettings.Cert()], certificates=[new TlsStreamSettings.Cert()],
alpn=[ALPN_OPTION.H2,ALPN_OPTION.HTTP1], alpn=[ALPN_OPTION.H2,ALPN_OPTION.HTTP1],
settings=new TlsStreamSettings.Settings()) { settings=new TlsStreamSettings.Settings()) {
@@ -545,6 +567,7 @@ class TlsStreamSettings extends XrayCommonClass {
this.cipherSuites = cipherSuites; this.cipherSuites = cipherSuites;
this.rejectUnknownSni = rejectUnknownSni; this.rejectUnknownSni = rejectUnknownSni;
this.disableSystemRoot = disableSystemRoot; this.disableSystemRoot = disableSystemRoot;
this.enableSessionResumption = enableSessionResumption;
this.certs = certificates; this.certs = certificates;
this.alpn = alpn; this.alpn = alpn;
this.settings = settings; this.settings = settings;
@@ -575,6 +598,7 @@ class TlsStreamSettings extends XrayCommonClass {
json.cipherSuites, json.cipherSuites,
json.rejectUnknownSni, json.rejectUnknownSni,
json.disableSystemRoot, json.disableSystemRoot,
json.enableSessionResumption,
certs, certs,
json.alpn, json.alpn,
settings, settings,
@@ -589,6 +613,7 @@ class TlsStreamSettings extends XrayCommonClass {
cipherSuites: this.cipherSuites, cipherSuites: this.cipherSuites,
rejectUnknownSni: this.rejectUnknownSni, rejectUnknownSni: this.rejectUnknownSni,
disableSystemRoot: this.disableSystemRoot, disableSystemRoot: this.disableSystemRoot,
enableSessionResumption: this.enableSessionResumption,
certificates: TlsStreamSettings.toJsonArray(this.certs), certificates: TlsStreamSettings.toJsonArray(this.certs),
alpn: this.alpn, alpn: this.alpn,
settings: this.settings, settings: this.settings,
@@ -881,7 +906,24 @@ RealityStreamSettings.Settings = class extends XrayCommonClass {
}; };
class SockoptStreamSettings extends XrayCommonClass { class SockoptStreamSettings extends XrayCommonClass {
constructor(acceptProxyProtocol = false, tcpFastOpen = false, mark = 0, tproxy="off", tcpMptcp = false, tcpNoDelay = false) { constructor(
acceptProxyProtocol = false,
tcpFastOpen = false,
mark = 0,
tproxy="off",
tcpMptcp = false,
tcpNoDelay = false,
domainStrategy = DOMAIN_STRATEGY_OPTION.USE_IP,
tcpMaxSeg = 1440,
dialerProxy = "",
tcpKeepAliveInterval = 0,
tcpKeepAliveIdle = 300,
tcpUserTimeout = 10000,
tcpcongestion = TCP_CONGESTION_OPTION.BBR,
V6Only = false,
tcpWindowClamp = 600,
interfaceName = "",
) {
super(); super();
this.acceptProxyProtocol = acceptProxyProtocol; this.acceptProxyProtocol = acceptProxyProtocol;
this.tcpFastOpen = tcpFastOpen; this.tcpFastOpen = tcpFastOpen;
@@ -889,6 +931,16 @@ class SockoptStreamSettings extends XrayCommonClass {
this.tproxy = tproxy; this.tproxy = tproxy;
this.tcpMptcp = tcpMptcp; this.tcpMptcp = tcpMptcp;
this.tcpNoDelay = tcpNoDelay; this.tcpNoDelay = tcpNoDelay;
this.domainStrategy = domainStrategy;
this.tcpMaxSeg = tcpMaxSeg;
this.dialerProxy = dialerProxy;
this.tcpKeepAliveInterval = tcpKeepAliveInterval;
this.tcpKeepAliveIdle = tcpKeepAliveIdle;
this.tcpUserTimeout = tcpUserTimeout;
this.tcpcongestion = tcpcongestion;
this.V6Only = V6Only;
this.tcpWindowClamp = tcpWindowClamp;
this.interfaceName = interfaceName;
} }
static fromJson(json = {}) { static fromJson(json = {}) {
@@ -900,6 +952,16 @@ class SockoptStreamSettings extends XrayCommonClass {
json.tproxy, json.tproxy,
json.tcpMptcp, json.tcpMptcp,
json.tcpNoDelay, json.tcpNoDelay,
json.domainStrategy,
json.tcpMaxSeg,
json.dialerProxy,
json.tcpKeepAliveInterval,
json.tcpKeepAliveIdle,
json.tcpUserTimeout,
json.tcpcongestion,
json.V6Only,
json.tcpWindowClamp,
json.interface,
); );
} }
@@ -911,6 +973,16 @@ class SockoptStreamSettings extends XrayCommonClass {
tproxy: this.tproxy, tproxy: this.tproxy,
tcpMptcp: this.tcpMptcp, tcpMptcp: this.tcpMptcp,
tcpNoDelay: this.tcpNoDelay, tcpNoDelay: this.tcpNoDelay,
domainStrategy: this.domainStrategy,
tcpMaxSeg: this.tcpMaxSeg,
dialerProxy: this.dialerProxy,
tcpKeepAliveInterval: this.tcpKeepAliveInterval,
tcpKeepAliveIdle: this.tcpKeepAliveIdle,
tcpUserTimeout: this.tcpUserTimeout,
tcpcongestion: this.tcpcongestion,
V6Only: this.V6Only,
tcpWindowClamp: this.tcpWindowClamp,
interface: this.interfaceName,
}; };
} }
} }

View File

@@ -13,15 +13,18 @@ import (
) )
func getRemoteIp(c *gin.Context) string { func getRemoteIp(c *gin.Context) string {
value := c.GetHeader("X-Forwarded-For") value := c.GetHeader("X-Real-IP")
if value != "" {
return value
}
value = c.GetHeader("X-Forwarded-For")
if value != "" { if value != "" {
ips := strings.Split(value, ",") ips := strings.Split(value, ",")
return ips[0] return ips[0]
} else {
addr := c.Request.RemoteAddr
ip, _, _ := net.SplitHostPort(addr)
return ip
} }
addr := c.Request.RemoteAddr
ip, _, _ := net.SplitHostPort(addr)
return ip
} }
func jsonMsg(c *gin.Context, msg string, err error) { func jsonMsg(c *gin.Context, msg string, err error) {
@@ -61,7 +64,18 @@ func html(c *gin.Context, name string, title string, data gin.H) {
data = gin.H{} data = gin.H{}
} }
data["title"] = title data["title"] = title
data["host"], _, _ = net.SplitHostPort(c.Request.Host) host := c.GetHeader("X-Forwarded-Host")
if host == "" {
host = c.GetHeader("X-Real-IP")
}
if host == "" {
var err error
host, _, err = net.SplitHostPort(c.Request.Host)
if err != nil {
host = c.Request.Host
}
}
data["host"] = host
data["request_uri"] = c.Request.RequestURI data["request_uri"] = c.Request.RequestURI
data["base_path"] = c.GetString("base_path") data["base_path"] = c.GetString("base_path")
c.HTML(http.StatusOK, name, getContext(data)) c.HTML(http.StatusOK, name, getContext(data))

View File

@@ -5,28 +5,62 @@
<a-switch v-model="inbound.stream.sockoptSwitch"></a-switch> <a-switch v-model="inbound.stream.sockoptSwitch"></a-switch>
</a-form-item> </a-form-item>
<template v-if="inbound.stream.sockoptSwitch"> <template v-if="inbound.stream.sockoptSwitch">
<a-form-item label="Route Mark">
<a-input-number v-model="inbound.stream.sockopt.mark" :min="0"></a-input-number>
</a-form-item>
<a-form-item label="TCP Keep Alive Interval">
<a-input-number v-model="inbound.stream.sockopt.tcpKeepAliveInterval" :min="0"></a-input-number>
</a-form-item>
<a-form-item label="TCP Keep Alive Idle">
<a-input-number v-model="inbound.stream.sockopt.tcpKeepAliveIdle" :min="0"></a-input-number>
</a-form-item>
<a-form-item label="TCP Max Seg">
<a-input-number v-model="inbound.stream.sockopt.tcpMaxSeg" :min="0"></a-input-number>
</a-form-item>
<a-form-item label="TCP User Timeout">
<a-input-number v-model="inbound.stream.sockopt.tcpUserTimeout" :min="0"></a-input-number>
</a-form-item>
<a-form-item label="TCP Window Clamp">
<a-input-number v-model="inbound.stream.sockopt.tcpWindowClamp" :min="0"></a-input-number>
</a-form-item>
<a-form-item label="Proxy Protocol"> <a-form-item label="Proxy Protocol">
<a-switch v-model="inbound.stream.sockopt.acceptProxyProtocol"></a-switch> <a-switch v-model="inbound.stream.sockopt.acceptProxyProtocol"></a-switch>
</a-form-item> </a-form-item>
<a-form-item label="TCP Fast Open"> <a-form-item label="TCP Fast Open">
<a-switch v-model.trim="inbound.stream.sockopt.tcpFastOpen"></a-switch> <a-switch v-model.trim="inbound.stream.sockopt.tcpFastOpen"></a-switch>
</a-form-item> </a-form-item>
<a-form-item label="Route Mark">
<a-input-number v-model="inbound.stream.sockopt.mark" :min="0"></a-input-number>
</a-form-item>
<a-form-item label="TProxy">
<a-select v-model="inbound.stream.sockopt.tproxy" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option value="off">Off</a-select-option>
<a-select-option value="redirect">Redirect</a-select-option>
<a-select-option value="tproxy">TProxy</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="Multipath TCP"> <a-form-item label="Multipath TCP">
<a-switch v-model.trim="inbound.stream.sockopt.tcpMptcp"></a-switch> <a-switch v-model.trim="inbound.stream.sockopt.tcpMptcp"></a-switch>
</a-form-item> </a-form-item>
<a-form-item label="TCP No-Delay"> <a-form-item label="TCP No-Delay">
<a-switch v-model.trim="inbound.stream.sockopt.tcpNoDelay"></a-switch> <a-switch v-model.trim="inbound.stream.sockopt.tcpNoDelay"></a-switch>
</a-form-item> </a-form-item>
<a-form-item label="V6 Only">
<a-switch v-model.trim="inbound.stream.sockopt.V6Only"></a-switch>
</a-form-item>
<a-form-item label='Domain Strategy'>
<a-select v-model="inbound.stream.sockopt.domainStrategy" style="width: 50%" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="key in DOMAIN_STRATEGY_OPTION" :value="key">[[ key ]]</a-select-option>
</a-select>
</a-form-item>
<a-form-item label='TCP Congestion'>
<a-select v-model="inbound.stream.sockopt.tcpcongestion" style="width: 50%" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="key in TCP_CONGESTION_OPTION" :value="key">[[ key ]]</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="TProxy">
<a-select v-model="inbound.stream.sockopt.tproxy" style="width: 50%" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option value="off">Off</a-select-option>
<a-select-option value="redirect">Redirect</a-select-option>
<a-select-option value="tproxy">TProxy</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="Dialer Proxy">
<a-input v-model="inbound.stream.sockopt.dialerProxy"></a-input>
</a-form-item>
<a-form-item label="Interface Name">
<a-input v-model="inbound.stream.sockopt.interfaceName"></a-input>
</a-form-item>
</template> </template>
</a-form> </a-form>
{{end}} {{end}}

View File

@@ -56,11 +56,14 @@
<a-form-item label="Allow Insecure"> <a-form-item label="Allow Insecure">
<a-switch v-model="inbound.stream.tls.settings.allowInsecure"></a-switch> <a-switch v-model="inbound.stream.tls.settings.allowInsecure"></a-switch>
</a-form-item> </a-form-item>
<a-form-item label="Reject Unknown SNI">
<a-switch v-model="inbound.stream.tls.rejectUnknownSni"></a-switch>
</a-form-item>
<a-form-item label="Disable System Root"> <a-form-item label="Disable System Root">
<a-switch v-model="inbound.stream.tls.settings.disableSystemRoot"></a-switch> <a-switch v-model="inbound.stream.tls.settings.disableSystemRoot"></a-switch>
</a-form-item> </a-form-item>
<a-form-item label="Reject Unknown SNI"> <a-form-item label="Session Resumption">
<a-switch v-model="inbound.stream.tls.rejectUnknownSni"></a-switch> <a-switch v-model="inbound.stream.tls.settings.enableSessionResumption"></a-switch>
</a-form-item> </a-form-item>
<template v-for="cert,index in inbound.stream.tls.certs"> <template v-for="cert,index in inbound.stream.tls.certs">
<a-form-item label='{{ i18n "certificate" }}'> <a-form-item label='{{ i18n "certificate" }}'>

View File

@@ -9,13 +9,17 @@ import (
func DomainValidatorMiddleware(domain string) gin.HandlerFunc { func DomainValidatorMiddleware(domain string) gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
host, _, _ := net.SplitHostPort(c.Request.Host) host := c.GetHeader("X-Forwarded-Host")
if host == "" {
if host != domain { host = c.GetHeader("X-Real-IP")
c.AbortWithStatus(http.StatusForbidden)
return
} }
if host == "" {
host, _, _ := net.SplitHostPort(c.Request.Host)
if host != domain {
c.AbortWithStatus(http.StatusForbidden)
return
}
c.Next() c.Next()
}
} }
} }