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
2 changes: 1 addition & 1 deletion .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
images: ghcr.io/${{ github.repository }}

- name: Build and push Docker image
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
Expand Down
6 changes: 3 additions & 3 deletions README.es_ES.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/xeefei/3x-ui/master/install.sh
## 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.4`:
Para instalar la versión deseada, agrega la versión al final del comando de instalación. Por ejemplo, ver `v2.3.6`:

```
bash <(curl -Ls https://raw.githubusercontent.com/xeefei/3x-ui/master/install.sh) v2.3.4
bash <(curl -Ls https://raw.githubusercontent.com/xeefei/3x-ui/master/install.sh) v2.3.6
```

## Certificado SSL
Expand Down Expand Up @@ -259,7 +259,7 @@ Nuestra plataforma ofrece compatibilidad con una amplia gama de arquitecturas y

</details>

## [Configuración WARP](https://gitlab.com/fscarmen/warp)
## Configuración WARP

<details>
<summary>Haz clic para detalles de la configuración WARP</summary>
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ apt update -y&&apt install -y curl&&apt install -y socat
------------
## 安装指定版本

若要安装指定的版本,请将该版本添加到安装命令的末尾。 e.g., ver `v2.3.5`:
若要安装指定的版本,请将该版本添加到安装命令的末尾。 e.g., ver `v2.3.6`:

```
bash <(curl -Ls https://raw.githubusercontent.com/xeefei/3x-ui/master/install.sh) v2.3.5
bash <(curl -Ls https://raw.githubusercontent.com/xeefei/3x-ui/master/install.sh) v2.3.6
```
------------
## 若你的VPS默认有防火墙,请在安装完成之后放行指定端口
Expand Down Expand Up @@ -468,9 +468,11 @@ systemctl restart x-ui

</details>


------------
## [WARP 配置](https://gitlab.com/fscarmen/warp)


<details>
<summary>点击查看 WARP 配置</summary>

Expand Down
7 changes: 3 additions & 4 deletions README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/xeefei/3x-ui/master/install.sh

## 安装指定版本


若需要安装指定的版本,请将该版本添加到安装命令的末尾。 e.g., ver `v2.3.4`:
若需要安装指定的版本,请将该版本添加到安装命令的末尾。 e.g., ver `v2.3.6`:

```
bash <(curl -Ls https://raw.githubusercontent.com/xeefei/3x-ui/master/install.sh) v2.3.4
bash <(curl -Ls https://raw.githubusercontent.com/xeefei/3x-ui/master/install.sh) v2.3.6
```

## SSL 认证
Expand Down Expand Up @@ -258,7 +257,7 @@ systemctl restart x-ui

</details>

## [WARP 配置](https://gitlab.com/fscarmen/warp)
## WARP 配置

<details>
<summary>点击查看 WARP 配置</summary>
Expand Down
2 changes: 1 addition & 1 deletion config/version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.3.5.3
2.3.6
1 change: 0 additions & 1 deletion sub/subJsonService.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,6 @@ func (s *SubJsonService) streamData(stream string) map[string]interface{} {
case "httpupgrade":
streamSettings["httpupgradeSettings"] = s.removeAcceptProxy(streamSettings["httpupgradeSettings"])
}

return streamSettings
}

Expand Down
130 changes: 76 additions & 54 deletions sub/subService.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,12 +202,11 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string {
case "ws":
ws, _ := stream["wsSettings"].(map[string]interface{})
obj["path"] = ws["path"].(string)
obj["host"] = ws["host"].(string)
if headers, ok := ws["headers"].(map[string]interface{}); ok {
hostFromHeaders := searchHost(headers)
if hostFromHeaders != "" {
obj["host"] = hostFromHeaders
}
if host, ok := ws["host"].(string); ok && len(host) > 0 {
obj["host"] = host
} else {
headers, _ := ws["headers"].(map[string]interface{})
obj["host"] = searchHost(headers)
}
case "http":
obj["net"] = "h2"
Expand All @@ -230,12 +229,20 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string {
case "httpupgrade":
httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{})
obj["path"] = httpupgrade["path"].(string)
obj["host"] = httpupgrade["host"].(string)
if headers, ok := httpupgrade["headers"].(map[string]interface{}); ok {
hostFromHeaders := searchHost(headers)
if hostFromHeaders != "" {
obj["host"] = hostFromHeaders
}
if host, ok := httpupgrade["host"].(string); ok && len(host) > 0 {
obj["host"] = host
} else {
headers, _ := httpupgrade["headers"].(map[string]interface{})
obj["host"] = searchHost(headers)
}
case "splithttp":
splithttp, _ := stream["splithttpSettings"].(map[string]interface{})
obj["path"] = splithttp["path"].(string)
if host, ok := splithttp["host"].(string); ok && len(host) > 0 {
obj["host"] = host
} else {
headers, _ := splithttp["headers"].(map[string]interface{})
obj["host"] = searchHost(headers)
}
}
security, _ := stream["security"].(string)
Expand Down Expand Up @@ -352,13 +359,11 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
case "ws":
ws, _ := stream["wsSettings"].(map[string]interface{})
params["path"] = ws["path"].(string)
params["host"] = ws["host"].(string)
headers, _ := ws["headers"].(map[string]interface{})
if headers != nil {
hostFromHeaders := searchHost(headers)
if hostFromHeaders != "" {
params["host"] = hostFromHeaders
}
if host, ok := ws["host"].(string); ok && len(host) > 0 {
params["host"] = host
} else {
headers, _ := ws["headers"].(map[string]interface{})
params["host"] = searchHost(headers)
}
case "http":
http, _ := stream["httpSettings"].(map[string]interface{})
Expand All @@ -380,13 +385,20 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
case "httpupgrade":
httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{})
params["path"] = httpupgrade["path"].(string)
params["host"] = httpupgrade["host"].(string)
headers, _ := httpupgrade["headers"].(map[string]interface{})
if headers != nil {
hostFromHeaders := searchHost(headers)
if hostFromHeaders != "" {
params["host"] = hostFromHeaders
}
if host, ok := httpupgrade["host"].(string); ok && len(host) > 0 {
params["host"] = host
} else {
headers, _ := httpupgrade["headers"].(map[string]interface{})
params["host"] = searchHost(headers)
}
case "splithttp":
splithttp, _ := stream["splithttpSettings"].(map[string]interface{})
params["path"] = splithttp["path"].(string)
if host, ok := splithttp["host"].(string); ok && len(host) > 0 {
params["host"] = host
} else {
headers, _ := splithttp["headers"].(map[string]interface{})
params["host"] = searchHost(headers)
}
}
security, _ := stream["security"].(string)
Expand Down Expand Up @@ -581,13 +593,11 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
case "ws":
ws, _ := stream["wsSettings"].(map[string]interface{})
params["path"] = ws["path"].(string)
params["host"] = ws["host"].(string)
headers, _ := ws["headers"].(map[string]interface{})
if headers != nil {
hostFromHeaders := searchHost(headers)
if hostFromHeaders != "" {
params["host"] = hostFromHeaders
}
if host, ok := ws["host"].(string); ok && len(host) > 0 {
params["host"] = host
} else {
headers, _ := ws["headers"].(map[string]interface{})
params["host"] = searchHost(headers)
}
case "http":
http, _ := stream["httpSettings"].(map[string]interface{})
Expand All @@ -609,13 +619,20 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
case "httpupgrade":
httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{})
params["path"] = httpupgrade["path"].(string)
params["host"] = httpupgrade["host"].(string)
headers, _ := httpupgrade["headers"].(map[string]interface{})
if headers != nil {
hostFromHeaders := searchHost(headers)
if hostFromHeaders != "" {
params["host"] = hostFromHeaders
}
if host, ok := httpupgrade["host"].(string); ok && len(host) > 0 {
params["host"] = host
} else {
headers, _ := httpupgrade["headers"].(map[string]interface{})
params["host"] = searchHost(headers)
}
case "splithttp":
splithttp, _ := stream["splithttpSettings"].(map[string]interface{})
params["path"] = splithttp["path"].(string)
if host, ok := splithttp["host"].(string); ok && len(host) > 0 {
params["host"] = host
} else {
headers, _ := splithttp["headers"].(map[string]interface{})
params["host"] = searchHost(headers)
}
}
security, _ := stream["security"].(string)
Expand Down Expand Up @@ -811,13 +828,11 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st
case "ws":
ws, _ := stream["wsSettings"].(map[string]interface{})
params["path"] = ws["path"].(string)
params["host"] = ws["host"].(string)
headers, _ := ws["headers"].(map[string]interface{})
if headers != nil {
hostFromHeaders := searchHost(headers)
if hostFromHeaders != "" {
params["host"] = hostFromHeaders
}
if host, ok := ws["host"].(string); ok && len(host) > 0 {
params["host"] = host
} else {
headers, _ := ws["headers"].(map[string]interface{})
params["host"] = searchHost(headers)
}
case "http":
http, _ := stream["httpSettings"].(map[string]interface{})
Expand All @@ -839,13 +854,20 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st
case "httpupgrade":
httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{})
params["path"] = httpupgrade["path"].(string)
params["host"] = httpupgrade["host"].(string)
headers, _ := httpupgrade["headers"].(map[string]interface{})
if headers != nil {
hostFromHeaders := searchHost(headers)
if hostFromHeaders != "" {
params["host"] = hostFromHeaders
}
if host, ok := httpupgrade["host"].(string); ok && len(host) > 0 {
params["host"] = host
} else {
headers, _ := httpupgrade["headers"].(map[string]interface{})
params["host"] = searchHost(headers)
}
case "splithttp":
splithttp, _ := stream["splithttpSettings"].(map[string]interface{})
params["path"] = splithttp["path"].(string)
if host, ok := splithttp["host"].(string); ok && len(host) > 0 {
params["host"] = host
} else {
headers, _ := splithttp["headers"].(map[string]interface{})
params["host"] = searchHost(headers)
}
}

Expand Down
39 changes: 34 additions & 5 deletions web/assets/js/model/outbound.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,14 @@ class WsStreamSettings extends CommonClass {
static fromJson(json={}) {
return new WsStreamSettings(
json.path,
json.host
json.host,
);
}

toJson() {
return {
path: this.path,
host: this.host,
headers: ObjectUtil.isEmpty(this.host) ? undefined : {Host: this.host},
};
}
}
Expand Down Expand Up @@ -288,15 +287,36 @@ class HttpUpgradeStreamSettings extends CommonClass {
static fromJson(json={}) {
return new HttpUpgradeStreamSettings(
json.path,
json.host
json.host,
);
}

toJson() {
return {
path: this.path,
host: this.host,
};
}
}

class SplitHTTPStreamSettings extends CommonClass {
constructor(path='/', host='') {
super();
this.path = path;
this.host = host;
}

static fromJson(json={}) {
return new SplitHTTPStreamSettings(
json.path,
json.host,
);
}

toJson() {
return {
path: this.path,
host: this.host,
headers: ObjectUtil.isEmpty(this.host) ? undefined : {Host: this.host},
};
}
}
Expand Down Expand Up @@ -404,6 +424,7 @@ class StreamSettings extends CommonClass {
quicSettings=new QuicStreamSettings(),
grpcSettings=new GrpcStreamSettings(),
httpupgradeSettings=new HttpUpgradeStreamSettings(),
splithttpSettings=new SplitHTTPStreamSettings(),
sockopt = undefined,
) {
super();
Expand All @@ -418,6 +439,7 @@ class StreamSettings extends CommonClass {
this.quic = quicSettings;
this.grpc = grpcSettings;
this.httpupgrade = httpupgradeSettings;
this.splithttp = splithttpSettings;
this.sockopt = sockopt;
}

Expand Down Expand Up @@ -450,6 +472,7 @@ class StreamSettings extends CommonClass {
QuicStreamSettings.fromJson(json.quicSettings),
GrpcStreamSettings.fromJson(json.grpcSettings),
HttpUpgradeStreamSettings.fromJson(json.httpupgradeSettings),
SplitHTTPStreamSettings.fromJson(json.splithttpSettings),
SockoptStreamSettings.fromJson(json.sockopt),
);
}
Expand All @@ -468,6 +491,7 @@ class StreamSettings extends CommonClass {
quicSettings: network === 'quic' ? this.quic.toJson() : undefined,
grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined,
httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined,
splithttpSettings: network === 'splithttp' ? this.splithttp.toJson() : undefined,
sockopt: this.sockopt != undefined ? this.sockopt.toJson() : undefined,
};
}
Expand Down Expand Up @@ -532,7 +556,7 @@ class Outbound extends CommonClass {

canEnableTls() {
if (![Protocols.VMess, Protocols.VLESS, Protocols.Trojan, Protocols.Shadowsocks].includes(this.protocol)) return false;
return ["tcp", "ws", "http", "quic", "grpc", "httpupgrade"].includes(this.stream.network);
return ["tcp", "ws", "http", "quic", "grpc", "httpupgrade" , "splithttp"].includes(this.stream.network);
}

//this is used for xtls-rprx-vision
Expand Down Expand Up @@ -653,6 +677,8 @@ class Outbound extends CommonClass {
stream.grpc = new GrpcStreamSettings(json.path, json.authority, json.type == 'multi');
} else if (network === 'httpupgrade') {
stream.httpupgrade = new HttpUpgradeStreamSettings(json.path,json.host);
} else if (network === 'splithttp') {
stream.splithttp = new SplitHTTPStreamSettings(json.path,json.host);
}

if(json.tls && json.tls == 'tls'){
Expand Down Expand Up @@ -700,6 +726,8 @@ class Outbound extends CommonClass {
url.searchParams.get('mode') == 'multi');
} else if (type === 'httpupgrade') {
stream.httpupgrade = new HttpUpgradeStreamSettings(path,host);
} else if (type === 'splithttp') {
stream.splithttp = new SplitHTTPStreamSettings(path,host);
}

if(security == 'tls'){
Expand Down Expand Up @@ -1056,6 +1084,7 @@ Outbound.WireguardSettings = class extends CommonClass {
super();
this.mtu = mtu;
this.secretKey = secretKey;
this.pubKey = secretKey.length>0 ? Wireguard.generateKeypair(secretKey).publicKey : '';
this.address = address instanceof Array ? address.join(',') : address;
this.workers = workers;
this.domainStrategy = domainStrategy;
Expand Down
Loading