mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-03-19 09:05:49 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6bb0b1787 | ||
|
|
c0b5d5506f | ||
|
|
a2f6d3b8dc | ||
|
|
80cd793154 | ||
|
|
d070a82b3d | ||
|
|
5ec16301a6 | ||
|
|
07245d614a |
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -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
|
||||||
|
|||||||
@@ -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}"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 认证
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
2.3.3
|
2.3.4
|
||||||
2
go.mod
2
go.mod
@@ -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
4
go.sum
@@ -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
22
main.go
@@ -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")
|
||||||
|
|||||||
@@ -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!")
|
||||||
|
|||||||
@@ -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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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}}
|
||||||
|
|||||||
@@ -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" }}'>
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user