Compare commits

..

7 Commits

10 changed files with 67 additions and 40 deletions

View File

@@ -38,6 +38,9 @@ jobs:
if [[ -z "$SOURCE_TAG" ]]; then if [[ -z "$SOURCE_TAG" ]]; then
SOURCE_TAG="${{ github.ref_name }}" SOURCE_TAG="${{ github.ref_name }}"
fi fi
if [[ -z "$SOURCE_TAG" ]]; then
SOURCE_TAG="${{ github.event.release.tag_name }}"
fi
if [[ -z "$SOURCE_TAG" ]]; then if [[ -z "$SOURCE_TAG" ]]; then
echo "Error: Could not determine a valid tag source. Input tag and context tag (github.ref_name) are both empty." echo "Error: Could not determine a valid tag source. Input tag and context tag (github.ref_name) are both empty."

View File

@@ -19,7 +19,7 @@ import (
var ( var (
Version_x byte = 25 Version_x byte = 25
Version_y byte = 7 Version_y byte = 7
Version_z byte = 24 Version_z byte = 25
) )
var ( var (

2
go.mod
View File

@@ -20,7 +20,7 @@ require (
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.10.0
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
github.com/vishvananda/netlink v1.3.1 github.com/vishvananda/netlink v1.3.1
github.com/xtls/reality v0.0.0-20250723121014-c6320729d93b github.com/xtls/reality v0.0.0-20250725142056-5b52a03d4fb7
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
golang.org/x/crypto v0.40.0 golang.org/x/crypto v0.40.0
golang.org/x/net v0.42.0 golang.org/x/net v0.42.0

4
go.sum
View File

@@ -77,8 +77,8 @@ github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW
github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4= github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4=
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/xtls/reality v0.0.0-20250723121014-c6320729d93b h1:HOOsQYu7/EzvpegY7uHiaeI9H/6OsHAOkREnJthdUW8= github.com/xtls/reality v0.0.0-20250725142056-5b52a03d4fb7 h1:Ript0vN+nSO33+Vj4n0mgNY5M+oOxFQJdrJ1VnwTBO0=
github.com/xtls/reality v0.0.0-20250723121014-c6320729d93b/go.mod h1:XxvnCCgBee4WWE0bc4E+a7wbk8gkJ/rS0vNVNtC5qp0= github.com/xtls/reality v0.0.0-20250725142056-5b52a03d4fb7/go.mod h1:XxvnCCgBee4WWE0bc4E+a7wbk8gkJ/rS0vNVNtC5qp0=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=

View File

@@ -122,13 +122,19 @@ func executePing(cmd *base.Command, args []string) {
} }
func printCertificates(certs []*x509.Certificate) { func printCertificates(certs []*x509.Certificate) {
var leaf *x509.Certificate
var length int
for _, cert := range certs { for _, cert := range certs {
if len(cert.DNSNames) == 0 { length += len(cert.Raw)
continue if len(cert.DNSNames) != 0 {
leaf = cert
} }
fmt.Println("Cert's signature algorithm: ", cert.SignatureAlgorithm.String()) }
fmt.Println("Cert's publicKey algorithm: ", cert.PublicKeyAlgorithm.String()) fmt.Println("Certificate chain's total length: ", length, "(certs count: "+strconv.Itoa(len(certs))+")")
fmt.Println("Cert's allowed domains: ", cert.DNSNames) if leaf != nil {
fmt.Println("Cert's signature algorithm: ", leaf.SignatureAlgorithm.String())
fmt.Println("Cert's publicKey algorithm: ", leaf.PublicKeyAlgorithm.String())
fmt.Println("Cert's allowed domains: ", leaf.DNSNames)
} }
} }

View File

@@ -77,7 +77,8 @@ func (c *UConn) HandshakeAddress() net.Address {
func (c *UConn) VerifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { func (c *UConn) VerifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
if c.Config.Show { if c.Config.Show {
localAddr := c.LocalAddr().String() localAddr := c.LocalAddr().String()
fmt.Printf("REALITY localAddr: %v\tis using X25519MLKEM768 for TLS' communication: %v\n", localAddr, c.HandshakeState.ServerHello.SelectedGroup == utls.X25519MLKEM768) curveID := *(*utls.CurveID)(unsafe.Pointer(reflect.ValueOf(c).Elem().FieldByName("curveID").UnsafeAddr()))
fmt.Printf("REALITY localAddr: %v\tis using X25519MLKEM768 for TLS' communication: %v\n", localAddr, curveID == utls.X25519MLKEM768)
fmt.Printf("REALITY localAddr: %v\tis using ML-DSA-65 for cert's extra verification: %v\n", localAddr, len(c.Config.Mldsa65Verify) > 0) fmt.Printf("REALITY localAddr: %v\tis using ML-DSA-65 for cert's extra verification: %v\n", localAddr, len(c.Config.Mldsa65Verify) > 0)
} }
p, _ := reflect.TypeOf(c.Conn).Elem().FieldByName("peerCertificates") p, _ := reflect.TypeOf(c.Conn).Elem().FieldByName("peerCertificates")

View File

@@ -64,26 +64,6 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
} }
} }
if config.TcpKeepAliveInterval > 0 || config.TcpKeepAliveIdle > 0 {
if config.TcpKeepAliveInterval > 0 {
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil {
return errors.New("failed to set TCP_KEEPINTVL", err)
}
}
if config.TcpKeepAliveIdle > 0 {
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, int(config.TcpKeepAliveIdle)); err != nil {
return errors.New("failed to set TCP_KEEPIDLE", err)
}
}
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil {
return errors.New("failed to set SO_KEEPALIVE", err)
}
} else if config.TcpKeepAliveInterval < 0 || config.TcpKeepAliveIdle < 0 {
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 0); err != nil {
return errors.New("failed to unset SO_KEEPALIVE", err)
}
}
if config.TcpCongestion != "" { if config.TcpCongestion != "" {
if err := syscall.SetsockoptString(int(fd), syscall.SOL_TCP, syscall.TCP_CONGESTION, config.TcpCongestion); err != nil { if err := syscall.SetsockoptString(int(fd), syscall.SOL_TCP, syscall.TCP_CONGESTION, config.TcpCongestion); err != nil {
return errors.New("failed to set TCP_CONGESTION", err) return errors.New("failed to set TCP_CONGESTION", err)

View File

@@ -3,6 +3,7 @@ package internet
import ( import (
"context" "context"
"math/rand" "math/rand"
gonet "net"
"syscall" "syscall"
"time" "time"
@@ -87,14 +88,34 @@ func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest ne
Dest: destAddr, Dest: destAddr,
}, nil }, nil
} }
goStdKeepAlive := time.Duration(0) // Chrome defaults
if sockopt != nil && (sockopt.TcpKeepAliveInterval != 0 || sockopt.TcpKeepAliveIdle != 0) { keepAliveConfig := gonet.KeepAliveConfig{
goStdKeepAlive = time.Duration(-1) Enable: true,
Idle: 45 * time.Second,
Interval: 45 * time.Second,
Count: -1,
}
keepAlive := time.Duration(0)
if sockopt != nil {
if sockopt.TcpKeepAliveIdle*sockopt.TcpKeepAliveInterval < 0 {
return nil, errors.New("invalid TcpKeepAliveIdle or TcpKeepAliveInterval value: ", sockopt.TcpKeepAliveIdle, " ", sockopt.TcpKeepAliveInterval)
}
if sockopt.TcpKeepAliveIdle < 0 || sockopt.TcpKeepAliveInterval < 0 {
keepAlive = -1
keepAliveConfig.Enable = false
}
if sockopt.TcpKeepAliveIdle > 0 {
keepAliveConfig.Idle = time.Duration(sockopt.TcpKeepAliveIdle) * time.Second
}
if sockopt.TcpKeepAliveInterval > 0 {
keepAliveConfig.Interval = time.Duration(sockopt.TcpKeepAliveInterval) * time.Second
}
} }
dialer := &net.Dialer{ dialer := &net.Dialer{
Timeout: time.Second * 16, Timeout: time.Second * 16,
LocalAddr: resolveSrcAddr(dest.Network, src), LocalAddr: resolveSrcAddr(dest.Network, src),
KeepAlive: goStdKeepAlive, KeepAlive: keepAlive,
KeepAliveConfig: keepAliveConfig,
} }
if sockopt != nil || len(d.controllers) > 0 { if sockopt != nil || len(d.controllers) > 0 {

View File

@@ -2,6 +2,7 @@ package internet
import ( import (
"context" "context"
gonet "net"
"os" "os"
"runtime" "runtime"
"strconv" "strconv"
@@ -88,9 +89,25 @@ func (dl *DefaultListener) Listen(ctx context.Context, addr net.Addr, sockopt *S
network = addr.Network() network = addr.Network()
address = addr.String() address = addr.String()
lc.Control = getControlFunc(ctx, sockopt, dl.controllers) lc.Control = getControlFunc(ctx, sockopt, dl.controllers)
// default disable keepalive
lc.KeepAlive = -1
if sockopt != nil { if sockopt != nil {
if sockopt.TcpKeepAliveInterval != 0 || sockopt.TcpKeepAliveIdle != 0 { if sockopt.TcpKeepAliveIdle*sockopt.TcpKeepAliveInterval < 0 {
lc.KeepAlive = time.Duration(-1) return nil, errors.New("invalid TcpKeepAliveIdle or TcpKeepAliveInterval value: ", sockopt.TcpKeepAliveIdle, " ", sockopt.TcpKeepAliveInterval)
}
lc.KeepAliveConfig = gonet.KeepAliveConfig{
Enable: false,
Idle: -1,
Interval: -1,
Count: -1,
}
if sockopt.TcpKeepAliveIdle > 0 {
lc.KeepAliveConfig.Enable = true
lc.KeepAliveConfig.Idle = time.Duration(sockopt.TcpKeepAliveIdle) * time.Second
}
if sockopt.TcpKeepAliveInterval > 0 {
lc.KeepAliveConfig.Enable = true
lc.KeepAliveConfig.Interval = time.Duration(sockopt.TcpKeepAliveInterval) * time.Second
} }
if sockopt.TcpMptcp { if sockopt.TcpMptcp {
lc.SetMultipathTCP(true) lc.SetMultipathTCP(true)

View File

@@ -70,11 +70,10 @@ func (v *Dispatcher) getInboundRay(ctx context.Context, dest net.Destination) (*
removeRay := func() { removeRay := func() {
v.Lock() v.Lock()
defer v.Unlock() defer v.Unlock()
// sometimes the entry is already removed by others, don't close again
if entry == v.conn { if entry == v.conn {
cancel() cancel()
v.removeRay() v.removeRay()
} else {
errors.LogError(ctx, "removeRay trying to remove a conn that not belongs to it, canceling.")
} }
} }
timer := signal.CancelAfterInactivity(ctx, removeRay, time.Minute) timer := signal.CancelAfterInactivity(ctx, removeRay, time.Minute)