diff --git a/common/net/tls.go b/common/net/tls.go index b2865503..77c0d7ca 100644 --- a/common/net/tls.go +++ b/common/net/tls.go @@ -3,8 +3,10 @@ package net import ( "crypto/rand" "crypto/rsa" + "crypto/sha256" "crypto/tls" "crypto/x509" + "encoding/hex" "encoding/pem" "fmt" "math/big" @@ -16,7 +18,11 @@ type Path interface { func ParseCert(certificate, privateKey string, path Path) (tls.Certificate, error) { if certificate == "" && privateKey == "" { - return newRandomTLSKeyPair() + var err error + certificate, privateKey, _, err = NewRandomTLSKeyPair() + if err != nil { + return tls.Certificate{}, err + } } cert, painTextErr := tls.X509KeyPair([]byte(certificate), []byte(privateKey)) if painTextErr == nil { @@ -32,10 +38,10 @@ func ParseCert(certificate, privateKey string, path Path) (tls.Certificate, erro return cert, nil } -func newRandomTLSKeyPair() (tls.Certificate, error) { +func NewRandomTLSKeyPair() (certificate string, privateKey string, fingerprint string, err error) { key, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { - return tls.Certificate{}, err + return } template := x509.Certificate{SerialNumber: big.NewInt(1)} certDER, err := x509.CreateCertificate( @@ -45,14 +51,15 @@ func newRandomTLSKeyPair() (tls.Certificate, error) { &key.PublicKey, key) if err != nil { - return tls.Certificate{}, err + return } - keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}) - certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}) - - tlsCert, err := tls.X509KeyPair(certPEM, keyPEM) + cert, err := x509.ParseCertificate(certDER) if err != nil { - return tls.Certificate{}, err + return } - return tlsCert, nil + hash := sha256.Sum256(cert.Raw) + fingerprint = hex.EncodeToString(hash[:]) + privateKey = string(pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})) + certificate = string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})) + return } diff --git a/component/http/http.go b/component/http/http.go index 63ea5be7..a2c44d85 100644 --- a/component/http/http.go +++ b/component/http/http.go @@ -69,7 +69,7 @@ func HttpRequestWithProxy(ctx context.Context, url, method string, header map[st TLSHandshakeTimeout: 10 * time.Second, ExpectContinueTimeout: 1 * time.Second, DialContext: func(ctx context.Context, network, address string) (net.Conn, error) { - if conn, err := inner.HandleTcp(address, specialProxy); err == nil { + if conn, err := inner.HandleTcp(inner.GetTunnel(), address, specialProxy); err == nil { return conn, nil } else { return dialer.DialContext(ctx, network, address) diff --git a/listener/http/server.go b/listener/http/server.go index e32b55dd..3c1eacdd 100644 --- a/listener/http/server.go +++ b/listener/http/server.go @@ -78,7 +78,7 @@ func NewWithConfig(config LC.AuthServer, tunnel C.Tunnel, additions ...inbound.A if tlsConfig.Certificates != nil { return nil, errors.New("certificate is unavailable in reality") } - realityBuilder, err = config.RealityConfig.Build() + realityBuilder, err = config.RealityConfig.Build(tunnel) if err != nil { return nil, err } diff --git a/listener/inner/tcp.go b/listener/inner/tcp.go index ee34ada6..95753fe9 100644 --- a/listener/inner/tcp.go +++ b/listener/inner/tcp.go @@ -3,8 +3,6 @@ package inner import ( "errors" "net" - "net/netip" - "strconv" N "github.com/metacubex/mihomo/common/net" C "github.com/metacubex/mihomo/constant" @@ -16,9 +14,13 @@ func New(t C.Tunnel) { tunnel = t } -func HandleTcp(address string, proxy string) (conn net.Conn, err error) { +func GetTunnel() C.Tunnel { + return tunnel +} + +func HandleTcp(tunnel C.Tunnel, address string, proxy string) (conn net.Conn, err error) { if tunnel == nil { - return nil, errors.New("tcp uninitialized") + return nil, errors.New("tunnel uninitialized") } // executor Parsed conn1, conn2 := N.Pipe() @@ -31,15 +33,8 @@ func HandleTcp(address string, proxy string) (conn net.Conn, err error) { if proxy != "" { metadata.SpecialProxy = proxy } - if h, port, err := net.SplitHostPort(address); err == nil { - if port, err := strconv.ParseUint(port, 10, 16); err == nil { - metadata.DstPort = uint16(port) - } - if ip, err := netip.ParseAddr(h); err == nil { - metadata.DstIP = ip - } else { - metadata.Host = h - } + if err = metadata.SetRemoteAddress(address); err != nil { + return nil, err } go tunnel.HandleTCPConn(conn2, metadata) diff --git a/listener/mixed/mixed.go b/listener/mixed/mixed.go index 6785b7fe..0ffdb02a 100644 --- a/listener/mixed/mixed.go +++ b/listener/mixed/mixed.go @@ -73,7 +73,7 @@ func NewWithConfig(config LC.AuthServer, tunnel C.Tunnel, additions ...inbound.A if tlsConfig.Certificates != nil { return nil, errors.New("certificate is unavailable in reality") } - realityBuilder, err = config.RealityConfig.Build() + realityBuilder, err = config.RealityConfig.Build(tunnel) if err != nil { return nil, err } diff --git a/listener/reality/reality.go b/listener/reality/reality.go index 222b036c..16ccc01c 100644 --- a/listener/reality/reality.go +++ b/listener/reality/reality.go @@ -9,6 +9,7 @@ import ( "net" "time" + C "github.com/metacubex/mihomo/constant" "github.com/metacubex/mihomo/listener/inner" "github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/ntp" @@ -27,7 +28,7 @@ type Config struct { Proxy string } -func (c Config) Build() (*Builder, error) { +func (c Config) Build(tunnel C.Tunnel) (*Builder, error) { realityConfig := &utls.RealityConfig{} realityConfig.SessionTicketsDisabled = true realityConfig.Type = "tcp" @@ -67,7 +68,7 @@ func (c Config) Build() (*Builder, error) { } realityConfig.DialContext = func(ctx context.Context, network, address string) (net.Conn, error) { - return inner.HandleTcp(address, c.Proxy) + return inner.HandleTcp(tunnel, address, c.Proxy) } return &Builder{realityConfig}, nil diff --git a/listener/sing_vless/server.go b/listener/sing_vless/server.go index 0614e4e6..137c8beb 100644 --- a/listener/sing_vless/server.go +++ b/listener/sing_vless/server.go @@ -106,7 +106,7 @@ func New(config LC.VlessServer, tunnel C.Tunnel, additions ...inbound.Addition) if tlsConfig.Certificates != nil { return nil, errors.New("certificate is unavailable in reality") } - realityBuilder, err = config.RealityConfig.Build() + realityBuilder, err = config.RealityConfig.Build(tunnel) if err != nil { return nil, err } diff --git a/listener/sing_vmess/server.go b/listener/sing_vmess/server.go index dd8f32af..dc80e8cb 100644 --- a/listener/sing_vmess/server.go +++ b/listener/sing_vmess/server.go @@ -90,7 +90,7 @@ func New(config LC.VmessServer, tunnel C.Tunnel, additions ...inbound.Addition) if tlsConfig.Certificates != nil { return nil, errors.New("certificate is unavailable in reality") } - realityBuilder, err = config.RealityConfig.Build() + realityBuilder, err = config.RealityConfig.Build(tunnel) if err != nil { return nil, err } diff --git a/listener/socks/tcp.go b/listener/socks/tcp.go index 55153607..9e42a625 100644 --- a/listener/socks/tcp.go +++ b/listener/socks/tcp.go @@ -72,7 +72,7 @@ func NewWithConfig(config LC.AuthServer, tunnel C.Tunnel, additions ...inbound.A if tlsConfig.Certificates != nil { return nil, errors.New("certificate is unavailable in reality") } - realityBuilder, err = config.RealityConfig.Build() + realityBuilder, err = config.RealityConfig.Build(tunnel) if err != nil { return nil, err } diff --git a/listener/trojan/server.go b/listener/trojan/server.go index 3141ab0b..299575a5 100644 --- a/listener/trojan/server.go +++ b/listener/trojan/server.go @@ -84,7 +84,7 @@ func New(config LC.TrojanServer, tunnel C.Tunnel, additions ...inbound.Addition) if tlsConfig.Certificates != nil { return nil, errors.New("certificate is unavailable in reality") } - realityBuilder, err = config.RealityConfig.Build() + realityBuilder, err = config.RealityConfig.Build(tunnel) if err != nil { return nil, err }