Compare commits

..
4 Commits
17 changed files with 63 additions and 52 deletions
+2
View File
@@ -11,6 +11,7 @@ on:
jobs:
check-assets:
runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
steps:
- name: Restore Geodat Cache
uses: actions/cache/restore@v5
@@ -75,6 +76,7 @@ jobs:
fail-fast: false
runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
env:
GOOS: ${{ matrix.goos}}
GOARCH: ${{ matrix.goarch }}
+2
View File
@@ -11,6 +11,7 @@ on:
jobs:
check-assets:
runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
steps:
- name: Restore Geodat Cache
uses: actions/cache/restore@v5
@@ -161,6 +162,7 @@ jobs:
fail-fast: false
runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
+2
View File
@@ -145,6 +145,8 @@
- [v2rayN](https://github.com/2dust/v2rayN)
- [GenyConnect](https://github.com/genyleap/GenyConnect)
- [OneXray](https://github.com/OneXray/OneXray)
- HarmonyOS
- [Hey](https://github.com/popsiclelmlm/Hey)
## Others that support VLESS, XTLS, REALITY, XUDP, PLUX...
+20
View File
@@ -57,6 +57,26 @@ func NewMetricsHandler(ctx context.Context, config *Config) (*MetricsHandler, er
})
return resp
}))
expvar.Publish("online", expvar.Func(func() interface{} {
resp := map[string]interface{}{}
c.statsManager.VisitOnlineMaps(func(name string, om feature_stats.OnlineMap) bool {
user := name
if parts := strings.Split(name, ">>>"); len(parts) >= 2 {
user = parts[1]
}
ips := map[string]int64{}
om.ForEach(func(ip string, lastSeen int64) bool {
ips[ip] = lastSeen
return true
})
resp[user] = map[string]interface{}{
"count": om.Count(),
"ips": ips,
}
return true
})
return resp
}))
expvar.Publish("observatory", expvar.Func(func() interface{} {
if c.observatory == nil {
common.Must(core.RequireFeatures(ctx, func(observatory extension.Observatory) error {
+7 -1
View File
@@ -273,7 +273,8 @@ type udpWorker struct {
checker *task.Periodic
activeConn map[connID]*udpConn
ctx context.Context
ctx context.Context
cone bool
}
func (w *udpWorker) getConnection(id connID) (*udpConn, bool) {
@@ -315,6 +316,9 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
src: source,
}
if originalDest.IsValid() {
if !w.cone {
id.dest = originalDest
}
b.UDP = &originalDest
}
conn, existing := w.getConnection(id)
@@ -414,6 +418,8 @@ func (w *udpWorker) Start() error {
return err
}
w.cone = w.ctx.Value("cone").(bool)
w.checker = &task.Periodic{
Interval: time.Minute,
Execute: w.clean,
+1
View File
@@ -16,6 +16,7 @@ const (
UseReadV = "xray.buf.readv"
UseFreedomSplice = "xray.buf.splice"
UseVmessPadding = "xray.vmess.padding"
UseCone = "xray.cone.disabled"
UseStrictJSON = "xray.json.strict"
BufferSize = "xray.ray.buffer.size"
+3
View File
@@ -49,6 +49,9 @@ func init() {
}
func GetGlobalID(ctx context.Context) (globalID [8]byte) {
if cone := ctx.Value("cone"); cone == nil || !cone.(bool) { // cone is nil only in some unit tests
return
}
if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Source.Network == net.Network_UDP &&
(inbound.Name == "dokodemo-door" || inbound.Name == "socks" || inbound.Name == "shadowsocks" || inbound.Name == "tun") {
h := blake3.New(8, BaseKey)
+4
View File
@@ -7,6 +7,7 @@ import (
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/platform"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/features"
"github.com/xtls/xray-core/features/dns"
@@ -186,6 +187,9 @@ func NewWithContext(ctx context.Context, config *Config) (*Instance, error) {
}
func initInstanceWithConfig(config *Config, server *Instance) (bool, error) {
server.ctx = context.WithValue(server.ctx, "cone",
platform.NewEnvFlag(platform.UseCone).GetValue(func() string { return "" }) != "true")
for _, appSettings := range config.App {
settings, err := appSettings.GetInstance()
if err != nil {
+1 -20
View File
@@ -14,7 +14,6 @@ import (
"strconv"
"strings"
"syscall"
"time"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
@@ -651,10 +650,8 @@ type TLSConfig struct {
MasterKeyLog string `json:"masterKeyLog"`
PinnedPeerCertSha256 string `json:"pinnedPeerCertSha256"`
VerifyPeerCertByName string `json:"verifyPeerCertByName"`
VerifyPeerCertInNames []string `json:"verifyPeerCertInNames"`
ECHServerKeys string `json:"echServerKeys"`
ECHConfigList string `json:"echConfigList"`
ECHForceQuery string `json:"echForceQuery"`
ECHSocketSettings *SocketConfig `json:"echSockopt"`
}
@@ -699,12 +696,7 @@ func (c *TLSConfig) Build() (proto.Message, error) {
config.MasterKeyLog = c.MasterKeyLog
if c.AllowInsecure {
if time.Now().After(time.Date(2026, 6, 1, 0, 0, 0, 0, time.UTC)) {
return nil, errors.PrintRemovedFeatureError(`"allowInsecure"`, `"pinnedPeerCertSha256"`)
} else {
errors.LogWarning(context.Background(), `"allowInsecure" will be removed automatically after 2026-06-01, please use "pinnedPeerCertSha256"(pcs) and "verifyPeerCertByName"(vcn) instead, PLEASE CONTACT YOUR SERVICE PROVIDER (AIRPORT)`)
config.AllowInsecure = true
}
return nil, errors.PrintRemovedFeatureError(`"allowInsecure"`, `"pinnedPeerCertSha256"(pcs) and "verifyPeerCertByName"(vcn)`)
}
if c.PinnedPeerCertSha256 != "" {
for v := range strings.SplitSeq(c.PinnedPeerCertSha256, ",") {
@@ -723,10 +715,6 @@ func (c *TLSConfig) Build() (proto.Message, error) {
config.PinnedPeerCertSha256 = append(config.PinnedPeerCertSha256, hashValue)
}
}
if c.VerifyPeerCertInNames != nil {
return nil, errors.PrintRemovedFeatureError(`"verifyPeerCertInNames"`, `"verifyPeerCertByName"`)
}
if c.VerifyPeerCertByName != "" {
for v := range strings.SplitSeq(c.VerifyPeerCertByName, ",") {
v = strings.TrimSpace(v)
@@ -744,13 +732,6 @@ func (c *TLSConfig) Build() (proto.Message, error) {
}
config.EchServerKeys = EchPrivateKey
}
switch c.ECHForceQuery {
case "none", "half", "full", "":
config.EchForceQuery = c.ECHForceQuery
default:
return nil, errors.New(`invalid "echForceQuery": `, c.ECHForceQuery)
}
config.EchForceQuery = c.ECHForceQuery
config.EchConfigList = c.ECHConfigList
if c.ECHSocketSettings != nil {
ss, err := c.ECHSocketSettings.Build()
+3 -1
View File
@@ -25,6 +25,7 @@ type Server struct {
config *ServerConfig
validator *Validator
policyManager policy.Manager
cone bool
}
// NewServer create a new Shadowsocks server.
@@ -46,6 +47,7 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
config: config,
validator: validator,
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
cone: ctx.Value("cone").(bool),
}
return s, nil
@@ -183,7 +185,7 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn stat.Connection, dis
data.UDP = &destination
if dest == nil {
if !s.cone || dest == nil {
dest = &destination
}
+3 -1
View File
@@ -28,6 +28,7 @@ import (
type Server struct {
config *ServerConfig
policyManager policy.Manager
cone bool
httpServer *http.Server
}
@@ -37,6 +38,7 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
s := &Server{
config: config,
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
cone: ctx.Value("cone").(bool),
}
httpConfig := &http.ServerConfig{
UserLevel: config.UserLevel,
@@ -255,7 +257,7 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn stat.Connection, dis
payload.UDP = &destination
if dest == nil {
if !s.cone || dest == nil {
dest = &destination
}
+3 -1
View File
@@ -38,6 +38,7 @@ type Server struct {
policyManager policy.Manager
validator *Validator
fallbacks map[string]map[string]map[string]*Fallback // or nil
cone bool
}
// NewServer creates a new trojan inbound handler.
@@ -58,6 +59,7 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
server := &Server{
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
validator: validator,
cone: ctx.Value("cone").(bool),
}
if config.Fallbacks != nil {
@@ -300,7 +302,7 @@ func (s *Server) handleUDPPayload(ctx context.Context, sessionPolicy policy.Sess
}
errors.LogInfo(ctx, "tunnelling request to ", destination)
if dest == nil {
if !s.cone || dest == nil {
dest = &destination
}
+3 -1
View File
@@ -52,6 +52,7 @@ func init() {
type Handler struct {
server *protocol.ServerSpec
policyManager policy.Manager
cone bool
encryption *encryption.ClientInstance
reverse *Reverse
@@ -79,6 +80,7 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
handler := &Handler{
server: server,
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
cone: ctx.Value("cone").(bool),
}
a := handler.server.User.Account.(*vless.MemoryAccount)
@@ -310,7 +312,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
clientReader := link.Reader // .(*pipe.Reader)
clientWriter := link.Writer // .(*pipe.Writer)
trafficState := proxy.NewTrafficState(account.ID.Bytes())
if request.Command == protocol.RequestCommandUDP && (requestAddons.Flow == vless.XRV || (request.Port != 53 && request.Port != 443)) {
if request.Command == protocol.RequestCommandUDP && (requestAddons.Flow == vless.XRV || (h.cone && request.Port != 53 && request.Port != 443)) {
request.Command = protocol.RequestCommandMux
request.Address = net.DomainAddress("v1.mux.cool")
request.Port = net.Port(666)
+3 -1
View File
@@ -31,6 +31,7 @@ import (
type Handler struct {
server *protocol.ServerSpec
policyManager policy.Manager
cone bool
}
// New creates a new VMess outbound handler.
@@ -47,6 +48,7 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
handler := &Handler{
server: server,
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
cone: ctx.Value("cone").(bool),
}
return handler, nil
@@ -146,7 +148,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
}
}, sessionPolicy.Timeouts.ConnectionIdle)
if request.Command == protocol.RequestCommandUDP && request.Port != 53 && request.Port != 443 {
if request.Command == protocol.RequestCommandUDP && h.cone && request.Port != 53 && request.Port != 443 {
request.Command = protocol.RequestCommandMux
request.Address = net.DomainAddress("v1.mux.cool")
request.Port = net.Port(666)
-1
View File
@@ -381,7 +381,6 @@ func (c *Config) GetTLSConfig(opts ...Option) *tls.Config {
PinnedPeerCertSha256: c.PinnedPeerCertSha256,
}
config := &tls.Config{
InsecureSkipVerify: c.AllowInsecure,
Rand: randCarrier,
ClientSessionCache: globalSessionCache,
RootCAs: root,
+4 -22
View File
@@ -177,8 +177,7 @@ func (x *Certificate) GetBuildChain() bool {
}
type Config struct {
state protoimpl.MessageState `protogen:"open.v1"`
AllowInsecure bool `protobuf:"varint,1,opt,name=allow_insecure,json=allowInsecure,proto3" json:"allow_insecure,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
// List of certificates to be served on server.
Certificate []*Certificate `protobuf:"bytes,2,rep,name=certificate,proto3" json:"certificate,omitempty"`
// Override server name.
@@ -205,7 +204,6 @@ type Config struct {
VerifyPeerCertByName []string `protobuf:"bytes,17,rep,name=verify_peer_cert_by_name,json=verifyPeerCertByName,proto3" json:"verify_peer_cert_by_name,omitempty"`
EchServerKeys []byte `protobuf:"bytes,18,opt,name=ech_server_keys,json=echServerKeys,proto3" json:"ech_server_keys,omitempty"`
EchConfigList string `protobuf:"bytes,19,opt,name=ech_config_list,json=echConfigList,proto3" json:"ech_config_list,omitempty"`
EchForceQuery string `protobuf:"bytes,20,opt,name=ech_force_query,json=echForceQuery,proto3" json:"ech_force_query,omitempty"`
EchSocketSettings *internet.SocketConfig `protobuf:"bytes,21,opt,name=ech_socket_settings,json=echSocketSettings,proto3" json:"ech_socket_settings,omitempty"`
PinnedPeerCertSha256 [][]byte `protobuf:"bytes,22,rep,name=pinned_peer_cert_sha256,json=pinnedPeerCertSha256,proto3" json:"pinned_peer_cert_sha256,omitempty"`
unknownFields protoimpl.UnknownFields
@@ -242,13 +240,6 @@ func (*Config) Descriptor() ([]byte, []int) {
return file_transport_internet_tls_config_proto_rawDescGZIP(), []int{1}
}
func (x *Config) GetAllowInsecure() bool {
if x != nil {
return x.AllowInsecure
}
return false
}
func (x *Config) GetCertificate() []*Certificate {
if x != nil {
return x.Certificate
@@ -354,13 +345,6 @@ func (x *Config) GetEchConfigList() string {
return ""
}
func (x *Config) GetEchForceQuery() string {
if x != nil {
return x.EchForceQuery
}
return ""
}
func (x *Config) GetEchSocketSettings() *internet.SocketConfig {
if x != nil {
return x.EchSocketSettings
@@ -393,9 +377,8 @@ const file_transport_internet_tls_config_proto_rawDesc = "" +
"\x05Usage\x12\x10\n" +
"\fENCIPHERMENT\x10\x00\x12\x14\n" +
"\x10AUTHORITY_VERIFY\x10\x01\x12\x13\n" +
"\x0fAUTHORITY_ISSUE\x10\x02\"\xf5\x06\n" +
"\x06Config\x12%\n" +
"\x0eallow_insecure\x18\x01 \x01(\bR\rallowInsecure\x12J\n" +
"\x0fAUTHORITY_ISSUE\x10\x02\"\xa6\x06\n" +
"\x06Config\x12J\n" +
"\vcertificate\x18\x02 \x03(\v2(.xray.transport.internet.tls.CertificateR\vcertificate\x12\x1f\n" +
"\vserver_name\x18\x03 \x01(\tR\n" +
"serverName\x12#\n" +
@@ -413,8 +396,7 @@ const file_transport_internet_tls_config_proto_rawDesc = "" +
"\x11curve_preferences\x18\x10 \x03(\tR\x10curvePreferences\x126\n" +
"\x18verify_peer_cert_by_name\x18\x11 \x03(\tR\x14verifyPeerCertByName\x12&\n" +
"\x0fech_server_keys\x18\x12 \x01(\fR\rechServerKeys\x12&\n" +
"\x0fech_config_list\x18\x13 \x01(\tR\rechConfigList\x12&\n" +
"\x0fech_force_query\x18\x14 \x01(\tR\rechForceQuery\x12U\n" +
"\x0fech_config_list\x18\x13 \x01(\tR\rechConfigList\x12U\n" +
"\x13ech_socket_settings\x18\x15 \x01(\v2%.xray.transport.internet.SocketConfigR\x11echSocketSettings\x125\n" +
"\x17pinned_peer_cert_sha256\x18\x16 \x03(\fR\x14pinnedPeerCertSha256Bs\n" +
"\x1fcom.xray.transport.internet.tlsP\x01Z0github.com/xtls/xray-core/transport/internet/tls\xaa\x02\x1bXray.Transport.Internet.Tlsb\x06proto3"
+2 -3
View File
@@ -38,7 +38,7 @@ message Certificate {
}
message Config {
bool allow_insecure = 1;
// Number 1 was assigned and used by an legacy option.
// List of certificates to be served on server.
repeated Certificate certificate = 2;
@@ -81,8 +81,7 @@ message Config {
string ech_config_list = 19;
// Deprecated
string ech_force_query = 20;
// Number 20 was assigned and used by an legacy option.
SocketConfig ech_socket_settings = 21;