Run official Xray-core on nodes with full Reality, TLS, and routing.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
orohi
2026-07-29 05:41:11 +03:00
co-authored by Cursor
parent b48b936c27
commit c567693651
13 changed files with 831 additions and 325 deletions
+9 -2
View File
@@ -231,7 +231,7 @@ func ClientSubscriptionHosts(db *sql.DB, client *models.Client) ([]models.SubHos
rows, err := db.Query(`
SELECT i.id, i.tag, i.remark, p.code, p.name, i.port, i.network, i.security,
i.path, i.host, i.sni, i.fingerprint, i.flow, i.alpn,
i.reality_public_key, i.reality_short_id, i.ss_method, i.password,
i.reality_public_key, i.reality_short_id, i.spider_x, i.ss_method, i.password,
COALESCE(n.host, ''), COALESCE(n.name, ''),
COALESCE(n.status = 'online', FALSE),
COALESCE(ni.enabled AND n.status = 'online', FALSE)
@@ -256,7 +256,7 @@ ORDER BY i.sort_order ASC, i.tag ASC, n.name ASC NULLS LAST`, client.ID)
&h.InboundID, &h.Tag, &h.Remark, &h.ProtocolCode, &h.ProtocolName,
&h.Port, &h.Network, &h.Security,
&h.Path, &h.HostHeader, &h.SNI, &h.Fingerprint, &h.Flow, &h.ALPN,
&h.PublicKey, &h.ShortID, &h.SSMethod, &h.Password,
&h.PublicKey, &h.ShortID, &h.SpiderX, &h.SSMethod, &h.Password,
&h.Address, &h.NodeName,
&h.NodeOnline, &h.Available,
); err != nil {
@@ -363,6 +363,13 @@ func buildVLESSLink(uid, name string, h *models.SubHost) string {
if h.ShortID != "" {
parts = append(parts, "sid="+url.QueryEscape(h.ShortID))
}
spx := h.SpiderX
if spx == "" && h.Security == "reality" {
spx = "/"
}
if spx != "" {
parts = append(parts, "spx="+url.QueryEscape(spx))
}
return fmt.Sprintf("vless://%s@%s:%d?%s#%s", uid, h.Address, h.Port, strings.Join(parts, "&"), name)
}
+9
View File
@@ -187,6 +187,15 @@ CREATE TABLE IF NOT EXISTS client_inbounds (
`ALTER TABLE inbounds ADD COLUMN IF NOT EXISTS reality_short_id TEXT NOT NULL DEFAULT ''`,
`ALTER TABLE inbounds ADD COLUMN IF NOT EXISTS ss_method TEXT NOT NULL DEFAULT 'aes-128-gcm'`,
`ALTER TABLE inbounds ADD COLUMN IF NOT EXISTS password TEXT NOT NULL DEFAULT ''`,
`ALTER TABLE inbounds ADD COLUMN IF NOT EXISTS reality_short_ids TEXT NOT NULL DEFAULT ''`,
`ALTER TABLE inbounds ADD COLUMN IF NOT EXISTS spider_x TEXT NOT NULL DEFAULT '/'`,
`ALTER TABLE inbounds ADD COLUMN IF NOT EXISTS reality_xver INT NOT NULL DEFAULT 0`,
`ALTER TABLE inbounds ADD COLUMN IF NOT EXISTS fallback_dest TEXT NOT NULL DEFAULT ''`,
`ALTER TABLE inbounds ADD COLUMN IF NOT EXISTS fallbacks_json TEXT NOT NULL DEFAULT ''`,
`ALTER TABLE inbounds ADD COLUMN IF NOT EXISTS tls_cert_pem TEXT NOT NULL DEFAULT ''`,
`ALTER TABLE inbounds ADD COLUMN IF NOT EXISTS tls_key_pem TEXT NOT NULL DEFAULT ''`,
`ALTER TABLE inbounds ADD COLUMN IF NOT EXISTS sniffing BOOLEAN NOT NULL DEFAULT TRUE`,
`ALTER TABLE inbounds ADD COLUMN IF NOT EXISTS sniffing_route_only BOOLEAN NOT NULL DEFAULT FALSE`,
} {
if _, err := db.Exec(q); err != nil {
return err
+9
View File
@@ -347,8 +347,17 @@ ORDER BY p.sort_order`, nodeID)
"reality_private_key": in.RealityPrivateKey,
"reality_public_key": in.RealityPublicKey,
"reality_short_id": in.RealityShortID,
"reality_short_ids": in.RealityShortIDs,
"spider_x": in.SpiderX,
"reality_xver": in.RealityXver,
"ss_method": in.SSMethod,
"password": in.Password,
"fallback_dest": in.FallbackDest,
"fallbacks_json": in.FallbacksJSON,
"tls_cert_pem": in.TLSCertPEM,
"tls_key_pem": in.TLSKeyPEM,
"sniffing": in.Sniffing,
"sniffing_route_only": in.SniffingRouteOnly,
"clients": clientList,
})
}
+41 -4
View File
@@ -101,7 +101,10 @@ func scanInbound(scanner interface {
&in.Port, &in.Network, &in.Security, &in.Listen, &in.Enabled, &in.SortOrder, &in.Remark,
&in.Path, &in.Host, &in.SNI, &in.Fingerprint, &in.Flow, &in.ALPN,
&in.RealityDest, &in.RealityServerNames, &in.RealityPrivateKey, &in.RealityPublicKey, &in.RealityShortID,
&in.RealityShortIDs, &in.SpiderX, &in.RealityXver,
&in.SSMethod, &in.Password,
&in.FallbackDest, &in.FallbacksJSON, &in.TLSCertPEM, &in.TLSKeyPEM,
&in.Sniffing, &in.SniffingRouteOnly,
&in.CreatedAt, &in.UpdatedAt,
)
if err != nil {
@@ -115,7 +118,10 @@ i.id, i.profile_id, i.tag, i.protocol_id, p.code, p.name,
i.port, i.network, i.security, i.listen, i.enabled, i.sort_order, i.remark,
i.path, i.host, i.sni, i.fingerprint, i.flow, i.alpn,
i.reality_dest, i.reality_server_names, i.reality_private_key, i.reality_public_key, i.reality_short_id,
i.reality_short_ids, i.spider_x, i.reality_xver,
i.ss_method, i.password,
i.fallback_dest, i.fallbacks_json, i.tls_cert_pem, i.tls_key_pem,
i.sniffing, i.sniffing_route_only,
i.created_at, i.updated_at`
func ListInboundsByProfile(db *sql.DB, profileID uuid.UUID) ([]models.Inbound, error) {
@@ -175,6 +181,12 @@ func CreateInbound(db *sql.DB, in *models.Inbound) error {
if in.SSMethod == "" {
in.SSMethod = "aes-128-gcm"
}
if in.SpiderX == "" {
in.SpiderX = "/"
}
if in.RealityShortIDs == "" && in.RealityShortID != "" {
in.RealityShortIDs = in.RealityShortID
}
now := time.Now().UTC()
in.CreatedAt = now
in.UpdatedAt = now
@@ -183,18 +195,27 @@ INSERT INTO inbounds (
id, profile_id, tag, protocol_id, port, network, security, listen, enabled, sort_order, remark,
path, host, sni, fingerprint, flow, alpn,
reality_dest, reality_server_names, reality_private_key, reality_public_key, reality_short_id,
ss_method, password, created_at, updated_at
reality_short_ids, spider_x, reality_xver,
ss_method, password,
fallback_dest, fallbacks_json, tls_cert_pem, tls_key_pem,
sniffing, sniffing_route_only, created_at, updated_at
) VALUES (
$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,
$12,$13,$14,$15,$16,$17,
$18,$19,$20,$21,$22,
$23,$24,$25,$26
$23,$24,$25,
$26,$27,
$28,$29,$30,$31,
$32,$33,$34,$35
)`,
in.ID, in.ProfileID, in.Tag, in.ProtocolID, in.Port, in.Network, in.Security, in.Listen,
in.Enabled, in.SortOrder, in.Remark,
in.Path, in.Host, in.SNI, in.Fingerprint, in.Flow, in.ALPN,
in.RealityDest, in.RealityServerNames, in.RealityPrivateKey, in.RealityPublicKey, in.RealityShortID,
in.SSMethod, in.Password, in.CreatedAt, in.UpdatedAt,
in.RealityShortIDs, in.SpiderX, in.RealityXver,
in.SSMethod, in.Password,
in.FallbackDest, in.FallbacksJSON, in.TLSCertPEM, in.TLSKeyPEM,
in.Sniffing, in.SniffingRouteOnly, in.CreatedAt, in.UpdatedAt,
)
return err
}
@@ -206,20 +227,33 @@ func UpdateInbound(db *sql.DB, in *models.Inbound) error {
if in.SSMethod == "" {
in.SSMethod = "aes-128-gcm"
}
if in.SpiderX == "" {
in.SpiderX = "/"
}
if in.RealityShortIDs == "" && in.RealityShortID != "" {
in.RealityShortIDs = in.RealityShortID
}
_, err := db.Exec(`
UPDATE inbounds SET
tag = $2, protocol_id = $3, port = $4, network = $5, security = $6,
listen = $7, enabled = $8, sort_order = $9, remark = $10,
path = $11, host = $12, sni = $13, fingerprint = $14, flow = $15, alpn = $16,
reality_dest = $17, reality_server_names = $18, reality_private_key = $19,
reality_public_key = $20, reality_short_id = $21, ss_method = $22, password = $23,
reality_public_key = $20, reality_short_id = $21,
reality_short_ids = $22, spider_x = $23, reality_xver = $24,
ss_method = $25, password = $26,
fallback_dest = $27, fallbacks_json = $28, tls_cert_pem = $29, tls_key_pem = $30,
sniffing = $31, sniffing_route_only = $32,
updated_at = NOW()
WHERE id = $1`,
in.ID, in.Tag, in.ProtocolID, in.Port, in.Network, in.Security,
in.Listen, in.Enabled, in.SortOrder, in.Remark,
in.Path, in.Host, in.SNI, in.Fingerprint, in.Flow, in.ALPN,
in.RealityDest, in.RealityServerNames, in.RealityPrivateKey, in.RealityPublicKey, in.RealityShortID,
in.RealityShortIDs, in.SpiderX, in.RealityXver,
in.SSMethod, in.Password,
in.FallbackDest, in.FallbacksJSON, in.TLSCertPEM, in.TLSKeyPEM,
in.Sniffing, in.SniffingRouteOnly,
)
return err
}
@@ -308,7 +342,10 @@ ORDER BY i.sort_order ASC, i.tag ASC`, nodeID, *n.ProfileID)
&in.Port, &in.Network, &in.Security, &in.Listen, &in.Enabled, &in.SortOrder, &in.Remark,
&in.Path, &in.Host, &in.SNI, &in.Fingerprint, &in.Flow, &in.ALPN,
&in.RealityDest, &in.RealityServerNames, &in.RealityPrivateKey, &in.RealityPublicKey, &in.RealityShortID,
&in.RealityShortIDs, &in.SpiderX, &in.RealityXver,
&in.SSMethod, &in.Password,
&in.FallbackDest, &in.FallbacksJSON, &in.TLSCertPEM, &in.TLSKeyPEM,
&in.Sniffing, &in.SniffingRouteOnly,
&in.CreatedAt, &in.UpdatedAt, &in.NodeEnabled,
); err != nil {
return nil, err