feat(xray): add hysteria v2 inbound and VLESS encryption support
This commit is contained in:
@@ -460,6 +460,10 @@ func buildVMess(base M, nc *panel.NodeConfig, users []panel.User, certFile, keyF
|
|||||||
}
|
}
|
||||||
|
|
||||||
func buildVLESS(base M, nc *panel.NodeConfig, users []panel.User, certFile, keyFile string) M {
|
func buildVLESS(base M, nc *panel.NodeConfig, users []panel.User, certFile, keyFile string) M {
|
||||||
|
if nc.Decryption != "" && nc.Decryption != "none" {
|
||||||
|
nlog.Core().Warn("sing-box does not support VLESS encryption (decryption), use xray kernel for this feature")
|
||||||
|
}
|
||||||
|
|
||||||
base["type"] = "vless"
|
base["type"] = "vless"
|
||||||
|
|
||||||
userList := make([]M, 0, len(users))
|
userList := make([]M, 0, len(users))
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ func buildConfig(kcfg config.KernelConfig, nc *panel.NodeConfig, users []panel.U
|
|||||||
} else {
|
} else {
|
||||||
nlog.Core().Warn("xray: unsupported protocol, no inbound configured — node will not accept connections",
|
nlog.Core().Warn("xray: unsupported protocol, no inbound configured — node will not accept connections",
|
||||||
"protocol", nc.Protocol,
|
"protocol", nc.Protocol,
|
||||||
"supported", "vmess, vless, trojan, shadowsocks, socks, http")
|
"supported", "vmess, vless, trojan, shadowsocks, hysteria, socks, http")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge panel routes and static config routes
|
// Merge panel routes and static config routes
|
||||||
@@ -225,6 +225,8 @@ func buildInbound(nc *panel.NodeConfig, users []panel.User, certFile, keyFile st
|
|||||||
return buildSocks(base, users)
|
return buildSocks(base, users)
|
||||||
case "http":
|
case "http":
|
||||||
return buildHTTP(base, nc, users, certFile, keyFile)
|
return buildHTTP(base, nc, users, certFile, keyFile)
|
||||||
|
case "hysteria":
|
||||||
|
return buildHysteria(base, nc, users, certFile, keyFile)
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -263,9 +265,13 @@ func buildVLESS(base M, nc *panel.NodeConfig, users []panel.User, certFile, keyF
|
|||||||
}
|
}
|
||||||
clients = append(clients, client)
|
clients = append(clients, client)
|
||||||
}
|
}
|
||||||
|
decryption := "none"
|
||||||
|
if nc.Decryption != "" {
|
||||||
|
decryption = nc.Decryption
|
||||||
|
}
|
||||||
base["settings"] = M{
|
base["settings"] = M{
|
||||||
"clients": clients,
|
"clients": clients,
|
||||||
"decryption": "none",
|
"decryption": decryption,
|
||||||
}
|
}
|
||||||
|
|
||||||
applyStreamSettings(base, nc, certFile, keyFile)
|
applyStreamSettings(base, nc, certFile, keyFile)
|
||||||
@@ -392,6 +398,66 @@ func buildHTTP(base M, nc *panel.NodeConfig, users []panel.User, certFile, keyFi
|
|||||||
return base
|
return base
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// buildHysteria creates a Hysteria v2 inbound for xray-core.
|
||||||
|
func buildHysteria(base M, nc *panel.NodeConfig, users []panel.User, certFile, keyFile string) M {
|
||||||
|
if nc.Version != 2 {
|
||||||
|
nlog.Core().Warn("xray: only supports hysteria v2, skipping v1 inbound")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
clients := make([]M, 0, len(users))
|
||||||
|
for _, u := range users {
|
||||||
|
clients = append(clients, M{
|
||||||
|
"auth": u.UUID,
|
||||||
|
"email": userEmail(u.ID),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
base["settings"] = M{"clients": clients}
|
||||||
|
|
||||||
|
ss := M{
|
||||||
|
"network": "hysteria",
|
||||||
|
"hysteriaSettings": M{
|
||||||
|
"version": nc.Version,
|
||||||
|
"udpIdleTimeout": 60,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if nc.UpMbps > 0 || nc.DownMbps > 0 {
|
||||||
|
quicParams := M{}
|
||||||
|
if nc.UpMbps > 0 {
|
||||||
|
quicParams["brutalUp"] = fmt.Sprintf("%d mbps", nc.UpMbps)
|
||||||
|
}
|
||||||
|
if nc.DownMbps > 0 {
|
||||||
|
quicParams["brutalDown"] = fmt.Sprintf("%d mbps", nc.DownMbps)
|
||||||
|
}
|
||||||
|
ss["finalMask"] = M{
|
||||||
|
"quicParams": quicParams,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if certFile != "" && keyFile != "" {
|
||||||
|
ss["security"] = "tls"
|
||||||
|
ss["tlsSettings"] = M{
|
||||||
|
"certificates": []M{
|
||||||
|
{
|
||||||
|
"certificateFile": certFile,
|
||||||
|
"keyFile": keyFile,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"alpn": []string{"h3"},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nlog.Core().Warn("hysteria requires TLS certificate files; configure cert_mode (self, file, http, dns, or content)")
|
||||||
|
}
|
||||||
|
|
||||||
|
if nc.GetProxyProtocol() {
|
||||||
|
ss["sockopt"] = M{"acceptProxyProtocol": true}
|
||||||
|
}
|
||||||
|
|
||||||
|
base["streamSettings"] = ss
|
||||||
|
return base
|
||||||
|
}
|
||||||
|
|
||||||
func applyStreamSettings(base M, nc *panel.NodeConfig, certFile, keyFile string) {
|
func applyStreamSettings(base M, nc *panel.NodeConfig, certFile, keyFile string) {
|
||||||
ss := M{}
|
ss := M{}
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ func (x *Xray) Name() string { return "xray" }
|
|||||||
func (x *Xray) Protocols() []string {
|
func (x *Xray) Protocols() []string {
|
||||||
return []string{
|
return []string{
|
||||||
"vmess", "vless", "trojan", "shadowsocks",
|
"vmess", "vless", "trojan", "shadowsocks",
|
||||||
"socks", "http", "dokodemo-door",
|
"hysteria", "socks", "http", "dokodemo-door",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ type NodeConfig struct {
|
|||||||
// VMess / VLESS
|
// VMess / VLESS
|
||||||
TLS int `json:"tls,omitempty"`
|
TLS int `json:"tls,omitempty"`
|
||||||
Flow string `json:"flow,omitempty"`
|
Flow string `json:"flow,omitempty"`
|
||||||
|
Decryption string `json:"decryption,omitempty"`
|
||||||
TLSSettings map[string]interface{} `json:"tls_settings,omitempty"`
|
TLSSettings map[string]interface{} `json:"tls_settings,omitempty"`
|
||||||
|
|
||||||
// Trojan
|
// Trojan
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ func (w *WSClient) connect(ctx context.Context) error {
|
|||||||
q.Set("node_id", strconv.Itoa(w.nodeID))
|
q.Set("node_id", strconv.Itoa(w.nodeID))
|
||||||
u.RawQuery = q.Encode()
|
u.RawQuery = q.Encode()
|
||||||
|
|
||||||
nlog.Core().Debug("ws connecting", "url", u.Host)
|
nlog.Core().Debug("ws connecting", "url", u.String())
|
||||||
|
|
||||||
dialer := websocket.Dialer{
|
dialer := websocket.Dialer{
|
||||||
HandshakeTimeout: w.cfg.HandshakeTimeout,
|
HandshakeTimeout: w.cfg.HandshakeTimeout,
|
||||||
|
|||||||
Reference in New Issue
Block a user