diff --git a/common/protocol/tls/cert/cert.go b/common/protocol/tls/cert/cert.go index c5972aadd4b..75902ce8570 100644 --- a/common/protocol/tls/cert/cert.go +++ b/common/protocol/tls/cert/cert.go @@ -13,6 +13,7 @@ import ( "time" "github.com/v2fly/v2ray-core/v5/common" + "github.com/v2fly/v2ray-core/v5/common/net" ) //go:generate go run github.com/v2fly/v2ray-core/v5/common/errors/errorgen @@ -76,6 +77,12 @@ func CommonName(name string) Option { } } +func IPAddresses(ip ...net.IP) Option { + return func(c *x509.Certificate) { + c.IPAddresses = ip + } +} + func KeyUsage(usage x509.KeyUsage) Option { return func(c *x509.Certificate) { c.KeyUsage = usage diff --git a/testing/scenarios/tls_test.go b/testing/scenarios/tls_test.go index 0b28259eabc..7c69162457e 100644 --- a/testing/scenarios/tls_test.go +++ b/testing/scenarios/tls_test.go @@ -253,6 +253,233 @@ func TestAutoIssuingCertificate(t *testing.T) { } } +func TestIPAddressesCertificate(t *testing.T) { + tcpServer := tcp.Server{ + MsgProcessor: xor, + } + dest, err := tcpServer.Start() + common.Must(err) + defer tcpServer.Close() + + caCert, err := cert.Generate(nil, cert.IPAddresses(net.LocalHostIP.IP()), cert.Authority(true), cert.KeyUsage(x509.KeyUsageDigitalSignature|x509.KeyUsageKeyEncipherment|x509.KeyUsageCertSign)) + common.Must(err) + certPEM, keyPEM := caCert.ToPEM() + + userID := protocol.NewID(uuid.New()) + serverPort := tcp.PickPort() + serverConfig := &core.Config{ + Inbound: []*core.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: net.SinglePortRange(serverPort), + Listen: net.NewIPOrDomain(net.LocalHostIP), + StreamSettings: &internet.StreamConfig{ + SecurityType: serial.GetMessageType(&tls.Config{}), + SecuritySettings: []*anypb.Any{ + serial.ToTypedMessage(&tls.Config{ + Certificate: []*tls.Certificate{{ + Certificate: certPEM, + Key: keyPEM, + }}, + }), + }, + }, + }), + ProxySettings: serial.ToTypedMessage(&inbound.Config{ + User: []*protocol.User{ + { + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + }), + }, + }, + }), + }, + }, + Outbound: []*core.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&freedom.Config{}), + }, + }, + } + + clientPort := tcp.PickPort() + clientConfig := &core.Config{ + Inbound: []*core.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: net.SinglePortRange(clientPort), + Listen: net.NewIPOrDomain(net.LocalHostIP), + }), + ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ + Address: net.NewIPOrDomain(dest.Address), + Port: uint32(dest.Port), + NetworkList: &net.NetworkList{ + Network: []net.Network{net.Network_TCP}, + }, + }), + }, + }, + Outbound: []*core.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&outbound.Config{ + Receiver: []*protocol.ServerEndpoint{ + { + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: []*protocol.User{ + { + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + }), + }, + }, + }, + }, + }), + SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{ + StreamSettings: &internet.StreamConfig{ + SecurityType: serial.GetMessageType(&tls.Config{}), + SecuritySettings: []*anypb.Any{ + serial.ToTypedMessage(&tls.Config{ + DisableSystemRoot: true, + Certificate: []*tls.Certificate{{ + Certificate: certPEM, + Usage: tls.Certificate_AUTHORITY_VERIFY, + }}, + }), + }, + }, + }), + }, + }, + } + + servers, err := InitializeServerConfigs(serverConfig, clientConfig) + common.Must(err) + defer CloseAllServers(servers) + + for i := 0; i < 10; i++ { + if err := testTCPConn(clientPort, 1024, time.Second*20)(); err != nil { + t.Error(err) + } + } +} + +func TestDNSNamesCertificate(t *testing.T) { + tcpServer := tcp.Server{ + MsgProcessor: xor, + } + dest, err := tcpServer.Start() + common.Must(err) + defer tcpServer.Close() + + caCert, err := cert.Generate(nil, cert.DNSNames("v2fly.org"), cert.Authority(true), cert.KeyUsage(x509.KeyUsageDigitalSignature|x509.KeyUsageKeyEncipherment|x509.KeyUsageCertSign)) + common.Must(err) + certPEM, keyPEM := caCert.ToPEM() + + userID := protocol.NewID(uuid.New()) + serverPort := tcp.PickPort() + serverConfig := &core.Config{ + Inbound: []*core.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: net.SinglePortRange(serverPort), + Listen: net.NewIPOrDomain(net.LocalHostIP), + StreamSettings: &internet.StreamConfig{ + SecurityType: serial.GetMessageType(&tls.Config{}), + SecuritySettings: []*anypb.Any{ + serial.ToTypedMessage(&tls.Config{ + Certificate: []*tls.Certificate{{ + Certificate: certPEM, + Key: keyPEM, + }}, + }), + }, + }, + }), + ProxySettings: serial.ToTypedMessage(&inbound.Config{ + User: []*protocol.User{ + { + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + }), + }, + }, + }), + }, + }, + Outbound: []*core.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&freedom.Config{}), + }, + }, + } + + clientPort := tcp.PickPort() + clientConfig := &core.Config{ + Inbound: []*core.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: net.SinglePortRange(clientPort), + Listen: net.NewIPOrDomain(net.LocalHostIP), + }), + ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ + Address: net.NewIPOrDomain(dest.Address), + Port: uint32(dest.Port), + NetworkList: &net.NetworkList{ + Network: []net.Network{net.Network_TCP}, + }, + }), + }, + }, + Outbound: []*core.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&outbound.Config{ + Receiver: []*protocol.ServerEndpoint{ + { + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: []*protocol.User{ + { + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + }), + }, + }, + }, + }, + }), + SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{ + StreamSettings: &internet.StreamConfig{ + SecurityType: serial.GetMessageType(&tls.Config{}), + SecuritySettings: []*anypb.Any{ + serial.ToTypedMessage(&tls.Config{ + DisableSystemRoot: true, + ServerName: "v2fly.org", + Certificate: []*tls.Certificate{{ + Certificate: certPEM, + Usage: tls.Certificate_AUTHORITY_VERIFY, + }}, + }), + }, + }, + }), + }, + }, + } + + servers, err := InitializeServerConfigs(serverConfig, clientConfig) + common.Must(err) + defer CloseAllServers(servers) + + for i := 0; i < 10; i++ { + if err := testTCPConn(clientPort, 1024, time.Second*20)(); err != nil { + t.Error(err) + } + } +} + func TestTLSOverKCP(t *testing.T) { tcpServer := tcp.Server{ MsgProcessor: xor, diff --git a/transport/internet/tls/config.go b/transport/internet/tls/config.go index 1d03a850c55..d73f81c3f7e 100644 --- a/transport/internet/tls/config.go +++ b/transport/internet/tls/config.go @@ -303,8 +303,13 @@ type Option func(*tls.Config) // WithDestination sets the server name in TLS config. func WithDestination(dest net.Destination) Option { return func(config *tls.Config) { - if dest.Address.Family().IsDomain() && config.ServerName == "" { - config.ServerName = dest.Address.Domain() + if config.ServerName == "" { + switch dest.Address.Family() { + case net.AddressFamilyDomain: + config.ServerName = dest.Address.Domain() + case net.AddressFamilyIPv4, net.AddressFamilyIPv6: + config.ServerName = dest.Address.IP().String() + } } } }