mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-04-29 16:58:34 +00:00
THE NEXT FUTURE becomes THE REALITY NOW
Thank @yuhan6665 for testing
This commit is contained in:
parent
15999e5c2a
commit
4d2e2b24d3
20 changed files with 1054 additions and 83 deletions
|
@ -2,13 +2,17 @@ package conf
|
|||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"math"
|
||||
"net/url"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/platform/filesystem"
|
||||
"github.com/xtls/xray-core/common/protocol"
|
||||
"github.com/xtls/xray-core/common/serial"
|
||||
|
@ -18,6 +22,7 @@ import (
|
|||
"github.com/xtls/xray-core/transport/internet/http"
|
||||
"github.com/xtls/xray-core/transport/internet/kcp"
|
||||
"github.com/xtls/xray-core/transport/internet/quic"
|
||||
"github.com/xtls/xray-core/transport/internet/reality"
|
||||
"github.com/xtls/xray-core/transport/internet/tcp"
|
||||
"github.com/xtls/xray-core/transport/internet/tls"
|
||||
"github.com/xtls/xray-core/transport/internet/websocket"
|
||||
|
@ -509,6 +514,170 @@ func (c *XTLSConfig) Build() (proto.Message, error) {
|
|||
return config, nil
|
||||
}
|
||||
|
||||
type REALITYConfig struct {
|
||||
Show bool `json:"show"`
|
||||
Dest json.RawMessage `json:"dest"`
|
||||
Type string `json:"type"`
|
||||
Xver uint64 `json:"xver"`
|
||||
ServerNames []string `json:"serverNames"`
|
||||
PrivateKey string `json:"privateKey"`
|
||||
MinClientVer string `json:"minClientVer"`
|
||||
MaxClientVer string `json:"maxClientVer"`
|
||||
MaxTimeDiff uint64 `json:"maxTimeDiff"`
|
||||
ShortIds []string `json:"shortIds"`
|
||||
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
ServerName string `json:"serverName"`
|
||||
PublicKey string `json:"publicKey"`
|
||||
ShortId string `json:"shortId"`
|
||||
SpiderX string `json:"spiderX"`
|
||||
}
|
||||
|
||||
func (c *REALITYConfig) Build() (proto.Message, error) {
|
||||
config := new(reality.Config)
|
||||
config.Show = c.Show
|
||||
var err error
|
||||
if c.Dest != nil {
|
||||
var i uint16
|
||||
var s string
|
||||
if err = json.Unmarshal(c.Dest, &i); err == nil {
|
||||
s = strconv.Itoa(int(i))
|
||||
} else {
|
||||
_ = json.Unmarshal(c.Dest, &s)
|
||||
}
|
||||
if c.Type == "" && s != "" {
|
||||
switch s[0] {
|
||||
case '@', '/':
|
||||
c.Type = "unix"
|
||||
if s[0] == '@' && len(s) > 1 && s[1] == '@' && (runtime.GOOS == "linux" || runtime.GOOS == "android") {
|
||||
fullAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path)) // may need padding to work with haproxy
|
||||
copy(fullAddr, s[1:])
|
||||
s = string(fullAddr)
|
||||
}
|
||||
default:
|
||||
if _, err = strconv.Atoi(s); err == nil {
|
||||
s = "127.0.0.1:" + s
|
||||
}
|
||||
if _, _, err = net.SplitHostPort(s); err == nil {
|
||||
c.Type = "tcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
if c.Type == "" {
|
||||
return nil, newError(`please fill in a valid value for "dest"`)
|
||||
}
|
||||
if c.Xver > 2 {
|
||||
return nil, newError(`invalid PROXY protocol version, "xver" only accepts 0, 1, 2`)
|
||||
}
|
||||
if len(c.ServerNames) == 0 {
|
||||
return nil, newError(`empty "serverNames"`)
|
||||
}
|
||||
if c.PrivateKey == "" {
|
||||
return nil, newError(`empty "privateKey"`)
|
||||
}
|
||||
if config.PrivateKey, err = base64.RawURLEncoding.DecodeString(c.PrivateKey); err != nil || len(config.PrivateKey) != 32 {
|
||||
return nil, newError(`invalid "privateKey": `, c.PrivateKey)
|
||||
}
|
||||
if c.MinClientVer != "" {
|
||||
config.MinClientVer = make([]byte, 3)
|
||||
var u uint64
|
||||
for i, s := range strings.Split(c.MinClientVer, ".") {
|
||||
if i == 3 {
|
||||
return nil, newError(`invalid "minClientVer": `, c.MinClientVer)
|
||||
}
|
||||
if u, err = strconv.ParseUint(s, 10, 8); err != nil {
|
||||
return nil, newError(`"minClientVer[`, i, `]" should be lesser than 256`)
|
||||
} else {
|
||||
config.MinClientVer[i] = byte(u)
|
||||
}
|
||||
}
|
||||
}
|
||||
if c.MaxClientVer != "" {
|
||||
config.MaxClientVer = make([]byte, 3)
|
||||
var u uint64
|
||||
for i, s := range strings.Split(c.MaxClientVer, ".") {
|
||||
if i == 3 {
|
||||
return nil, newError(`invalid "maxClientVer": `, c.MaxClientVer)
|
||||
}
|
||||
if u, err = strconv.ParseUint(s, 10, 8); err != nil {
|
||||
return nil, newError(`"maxClientVer[`, i, `]" should be lesser than 256`)
|
||||
} else {
|
||||
config.MaxClientVer[i] = byte(u)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(c.ShortIds) == 0 {
|
||||
return nil, newError(`empty "shortIds"`)
|
||||
}
|
||||
config.ShortIds = make([][]byte, len(c.ShortIds))
|
||||
for i, s := range c.ShortIds {
|
||||
config.ShortIds[i] = make([]byte, 8)
|
||||
if _, err = hex.Decode(config.ShortIds[i], []byte(s)); err != nil {
|
||||
return nil, newError(`invalid "shortIds[`, i, `]": `, s)
|
||||
}
|
||||
}
|
||||
config.Dest = s
|
||||
config.Type = c.Type
|
||||
config.Xver = c.Xver
|
||||
config.ServerNames = c.ServerNames
|
||||
config.MaxTimeDiff = c.MaxTimeDiff
|
||||
} else {
|
||||
if c.Fingerprint == "" {
|
||||
return nil, newError(`empty "fingerprint"`)
|
||||
}
|
||||
if config.Fingerprint = strings.ToLower(c.Fingerprint); tls.GetFingerprint(config.Fingerprint) == nil {
|
||||
return nil, newError(`unknown "fingerprint": `, config.Fingerprint)
|
||||
}
|
||||
if config.Fingerprint == "hellogolang" {
|
||||
return nil, newError(`invalid "fingerprint": `, config.Fingerprint)
|
||||
}
|
||||
if c.PublicKey == "" {
|
||||
return nil, newError(`empty "publicKey"`)
|
||||
}
|
||||
if config.PublicKey, err = base64.RawURLEncoding.DecodeString(c.PublicKey); err != nil || len(config.PublicKey) != 32 {
|
||||
return nil, newError(`invalid "publicKey": `, c.PublicKey)
|
||||
}
|
||||
if c.ShortId == "" {
|
||||
return nil, newError(`empty "shortId"`)
|
||||
}
|
||||
config.ShortId = make([]byte, 8)
|
||||
if _, err = hex.Decode(config.ShortId, []byte(c.ShortId)); err != nil {
|
||||
return nil, newError(`invalid "shortId": `, c.ShortId)
|
||||
}
|
||||
if c.SpiderX == "" {
|
||||
return nil, newError(`empty "spiderX"`)
|
||||
}
|
||||
if c.SpiderX[0] != '/' {
|
||||
return nil, newError(`invalid "spiderX": `, c.SpiderX)
|
||||
}
|
||||
config.SpiderY = make([]int64, 10)
|
||||
u, _ := url.Parse(c.SpiderX)
|
||||
q := u.Query()
|
||||
parse := func(param string, index int) {
|
||||
if q.Get(param) != "" {
|
||||
s := strings.Split(q.Get(param), "-")
|
||||
if len(s) == 1 {
|
||||
config.SpiderY[index], _ = strconv.ParseInt(s[0], 10, 64)
|
||||
config.SpiderY[index+1], _ = strconv.ParseInt(s[0], 10, 64)
|
||||
} else {
|
||||
config.SpiderY[index], _ = strconv.ParseInt(s[0], 10, 64)
|
||||
config.SpiderY[index+1], _ = strconv.ParseInt(s[1], 10, 64)
|
||||
}
|
||||
}
|
||||
q.Del(param)
|
||||
}
|
||||
parse("p", 0) // padding
|
||||
parse("c", 2) // concurrency
|
||||
parse("t", 4) // times
|
||||
parse("i", 6) // interval
|
||||
parse("r", 8) // return
|
||||
u.RawQuery = q.Encode()
|
||||
config.SpiderX = u.String()
|
||||
config.ServerName = c.ServerName
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
type TransportProtocol string
|
||||
|
||||
// Build implements Buildable.
|
||||
|
@ -598,19 +767,20 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
|||
}
|
||||
|
||||
type StreamConfig struct {
|
||||
Network *TransportProtocol `json:"network"`
|
||||
Security string `json:"security"`
|
||||
TLSSettings *TLSConfig `json:"tlsSettings"`
|
||||
XTLSSettings *XTLSConfig `json:"xtlsSettings"`
|
||||
TCPSettings *TCPConfig `json:"tcpSettings"`
|
||||
KCPSettings *KCPConfig `json:"kcpSettings"`
|
||||
WSSettings *WebSocketConfig `json:"wsSettings"`
|
||||
HTTPSettings *HTTPConfig `json:"httpSettings"`
|
||||
DSSettings *DomainSocketConfig `json:"dsSettings"`
|
||||
QUICSettings *QUICConfig `json:"quicSettings"`
|
||||
SocketSettings *SocketConfig `json:"sockopt"`
|
||||
GRPCConfig *GRPCConfig `json:"grpcSettings"`
|
||||
GUNConfig *GRPCConfig `json:"gunSettings"`
|
||||
Network *TransportProtocol `json:"network"`
|
||||
Security string `json:"security"`
|
||||
TLSSettings *TLSConfig `json:"tlsSettings"`
|
||||
XTLSSettings *XTLSConfig `json:"xtlsSettings"`
|
||||
REALITYSettings *REALITYConfig `json:"realitySettings"`
|
||||
TCPSettings *TCPConfig `json:"tcpSettings"`
|
||||
KCPSettings *KCPConfig `json:"kcpSettings"`
|
||||
WSSettings *WebSocketConfig `json:"wsSettings"`
|
||||
HTTPSettings *HTTPConfig `json:"httpSettings"`
|
||||
DSSettings *DomainSocketConfig `json:"dsSettings"`
|
||||
QUICSettings *QUICConfig `json:"quicSettings"`
|
||||
SocketSettings *SocketConfig `json:"sockopt"`
|
||||
GRPCConfig *GRPCConfig `json:"grpcSettings"`
|
||||
GUNConfig *GRPCConfig `json:"gunSettings"`
|
||||
}
|
||||
|
||||
// Build implements Buildable.
|
||||
|
@ -660,6 +830,21 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
|||
config.SecuritySettings = append(config.SecuritySettings, tm)
|
||||
config.SecurityType = tm.Type
|
||||
}
|
||||
if strings.EqualFold(c.Security, "reality") {
|
||||
if config.ProtocolName != "tcp" && config.ProtocolName != "http" && config.ProtocolName != "domainsocket" {
|
||||
return nil, newError("REALITY only supports TCP, H2 and DomainSocket for now.")
|
||||
}
|
||||
if c.REALITYSettings == nil {
|
||||
return nil, newError(`REALITY: Empty "realitySettings".`)
|
||||
}
|
||||
ts, err := c.REALITYSettings.Build()
|
||||
if err != nil {
|
||||
return nil, newError("Failed to build REALITY config.").Base(err)
|
||||
}
|
||||
tm := serial.ToTypedMessage(ts)
|
||||
config.SecuritySettings = append(config.SecuritySettings, tm)
|
||||
config.SecurityType = tm.Type
|
||||
}
|
||||
if c.TCPSettings != nil {
|
||||
ts, err := c.TCPSettings.Build()
|
||||
if err != nil {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue