mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-10-17 04:53:59 +00:00
WireGuard, MASQUE proxies: Use Xray-core's built-in lightweight TCP/IP stack instead of gVisor as well (#7156)
https://github.com/XTLS/Xray-core/pull/7130#issuecomment-6116258188 https://github.com/XTLS/Xray-core/pull/7130#issuecomment-6120742739 https://github.com/XTLS/Xray-core/pull/7130#issuecomment-6137264458 https://github.com/XTLS/Xray-core/pull/7156#issuecomment-6202933664 https://github.com/XTLS/Xray-core/pull/7156#issuecomment-6203239736
This commit is contained in:
@@ -25,10 +25,6 @@ import (
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
|
||||
|
||||
"github.com/xtls/xray-core/app/log"
|
||||
"github.com/xtls/xray-core/app/proxyman"
|
||||
@@ -64,54 +60,31 @@ const (
|
||||
masqueAuthorization = "Basic dUBleGFtcGxlLmNvbTpw"
|
||||
)
|
||||
|
||||
// masqueEcho answers what comes to the echo port of the server, TCP and UDP alike
|
||||
type masqueEcho struct{}
|
||||
|
||||
func (masqueEcho) HandleConnection(conn net.Conn, dest net.Destination) {
|
||||
defer conn.Close()
|
||||
if dest.Port != masqueEchoPort {
|
||||
return
|
||||
}
|
||||
b := make([]byte, 2048)
|
||||
for {
|
||||
n, err := conn.Read(b)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err := conn.Write(xor(b[:n])); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func startMasqueServer(t *testing.T, h2 bool) (net.Port, [32]byte) {
|
||||
dev, _, gstack, err := wireguard.CreateNetTUN([]netip.Addr{masqueServerV4, masqueServerV6}, nil, transmasque.MinPacketSize, false)
|
||||
dev, _, err := wireguard.CreateNetTUN([]netip.Addr{masqueServerV4, masqueServerV6}, nil, transmasque.MinPacketSize, masqueEcho{})
|
||||
common.Must(err)
|
||||
t.Cleanup(func() { dev.Close() })
|
||||
|
||||
for _, addr := range []netip.Addr{masqueServerV4, masqueServerV6} {
|
||||
proto := ipv4.ProtocolNumber
|
||||
if addr.Is6() {
|
||||
proto = ipv6.ProtocolNumber
|
||||
}
|
||||
local := tcpip.FullAddress{NIC: 1, Addr: tcpip.AddrFromSlice(addr.AsSlice()), Port: masqueEchoPort}
|
||||
l, err := gonet.ListenTCP(gstack, local, proto)
|
||||
common.Must(err)
|
||||
go func() {
|
||||
for {
|
||||
c, err := l.Accept()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
defer c.Close()
|
||||
b := make([]byte, 2048)
|
||||
for {
|
||||
n, err := c.Read(b)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err := c.Write(xor(b[:n])); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
}()
|
||||
u, err := gonet.DialUDP(gstack, &local, nil, proto)
|
||||
common.Must(err)
|
||||
go func() {
|
||||
b := make([]byte, 2048)
|
||||
for {
|
||||
n, addr, err := u.ReadFrom(b)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
u.WriteTo(xor(b[:n]), addr)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
var current atomic.Pointer[connectip.Conn]
|
||||
go func() {
|
||||
bufs := [][]byte{make([]byte, transmasque.MinPacketSize)}
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
package scenarios
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
//"time"
|
||||
"time"
|
||||
|
||||
"github.com/xtls/xray-core/app/log"
|
||||
"github.com/xtls/xray-core/app/proxyman"
|
||||
"github.com/xtls/xray-core/app/router"
|
||||
"github.com/xtls/xray-core/common"
|
||||
clog "github.com/xtls/xray-core/common/log"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/protocol"
|
||||
"github.com/xtls/xray-core/common/serial"
|
||||
core "github.com/xtls/xray-core/core"
|
||||
"github.com/xtls/xray-core/infra/conf"
|
||||
@@ -17,9 +20,18 @@ import (
|
||||
"github.com/xtls/xray-core/proxy/wireguard"
|
||||
"github.com/xtls/xray-core/testing/servers/tcp"
|
||||
"github.com/xtls/xray-core/testing/servers/udp"
|
||||
//"golang.org/x/sync/errgroup"
|
||||
"golang.org/x/crypto/curve25519"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
func wireguardPublicKey(private string) string {
|
||||
key, err := wireguard.ParseKey(private)
|
||||
common.Must(err)
|
||||
var public [32]byte
|
||||
curve25519.ScalarBaseMult(&public, key)
|
||||
return hex.EncodeToString(public[:])
|
||||
}
|
||||
|
||||
func TestWireguard(t *testing.T) {
|
||||
tcpServer := tcp.Server{
|
||||
MsgProcessor: xor,
|
||||
@@ -28,18 +40,44 @@ func TestWireguard(t *testing.T) {
|
||||
common.Must(err)
|
||||
defer tcpServer.Close()
|
||||
|
||||
serverPrivate, _ := conf.ParseWireGuardKey("EGs4lTSJPmgELx6YiJAmPR2meWi6bY+e9rTdCipSj10=")
|
||||
serverPublic, _ := conf.ParseWireGuardKey("osAMIyil18HeZXGGBDC9KpZoM+L2iGyXWVSYivuM9B0=")
|
||||
clientPrivate, _ := conf.ParseWireGuardKey("CPQSpgxgdQRZa5SUbT3HLv+mmDVHLW5YR/rQlzum/2I=")
|
||||
clientPublic, _ := conf.ParseWireGuardKey("MmLJ5iHFVVBp7VsB0hxfpQ0wEzAbT2KQnpQpj0+RtBw=")
|
||||
udpServer := udp.Server{
|
||||
MsgProcessor: xor,
|
||||
}
|
||||
udpDest, err := udpServer.Start()
|
||||
common.Must(err)
|
||||
defer udpServer.Close()
|
||||
|
||||
serverPrivate, _ := conf.ParseWireGuardKey("EGs4lTSJPmgELx6YiJAmPR2meWi6bY+e9rTdCipSj10=")
|
||||
clientPrivate, _ := conf.ParseWireGuardKey("CPQSpgxgdQRZa5SUbT3HLv+mmDVHLW5YR/rQlzum/2I=")
|
||||
|
||||
// What the client asks for is somewhere else, the stack of the server takes nothing that is for this machine.
|
||||
redirect := func(tag string, dest net.Destination) *core.OutboundHandlerConfig {
|
||||
return &core.OutboundHandlerConfig{
|
||||
Tag: tag,
|
||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
||||
DestinationOverride: &freedom.DestinationOverride{
|
||||
Server: &protocol.ServerEndpoint{
|
||||
Address: net.NewIPOrDomain(dest.Address),
|
||||
Port: uint32(dest.Port),
|
||||
},
|
||||
},
|
||||
FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Allow}},
|
||||
}),
|
||||
}
|
||||
}
|
||||
serverPort := udp.PickPort()
|
||||
serverConfig := &core.Config{
|
||||
App: []*serial.TypedMessage{
|
||||
serial.ToTypedMessage(&log.Config{
|
||||
ErrorLogLevel: clog.Severity_Debug,
|
||||
ErrorLogLevel: clog.Severity_Warning,
|
||||
ErrorLogType: log.LogType_Console,
|
||||
}),
|
||||
serial.ToTypedMessage(&router.Config{
|
||||
Rule: []*router.RoutingRule{
|
||||
{Networks: []net.Network{net.Network_TCP}, TargetTag: &router.RoutingRule_Tag{Tag: "tcp"}},
|
||||
{Networks: []net.Network{net.Network_UDP}, TargetTag: &router.RoutingRule_Tag{Tag: "udp"}},
|
||||
},
|
||||
}),
|
||||
},
|
||||
Inbound: []*core.InboundHandlerConfig{
|
||||
{
|
||||
@@ -48,60 +86,65 @@ func TestWireguard(t *testing.T) {
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&wireguard.DeviceConfig{
|
||||
IsClient: false,
|
||||
NoKernelTun: false,
|
||||
Endpoint: []string{"10.0.0.1"},
|
||||
Mtu: 1420,
|
||||
SecretKey: serverPrivate,
|
||||
Peers: []*wireguard.PeerConfig{{
|
||||
PublicKey: serverPublic,
|
||||
AllowedIps: []string{"0.0.0.0/0", "::0/0"},
|
||||
IsClient: false,
|
||||
Endpoint: []string{"10.0.0.1", "fd00::1"},
|
||||
Mtu: 1420,
|
||||
SecretKey: serverPrivate,
|
||||
Users: []*protocol.User{{
|
||||
Email: "love@xray.com",
|
||||
Account: serial.ToTypedMessage(&wireguard.PeerConfig{
|
||||
PublicKey: wireguardPublicKey(clientPrivate),
|
||||
AllowedIps: []string{"10.0.0.2/32", "fd00::2/128"},
|
||||
}),
|
||||
}},
|
||||
}),
|
||||
},
|
||||
},
|
||||
Outbound: []*core.OutboundHandlerConfig{
|
||||
{
|
||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
||||
FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Allow}},
|
||||
}),
|
||||
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{}),
|
||||
},
|
||||
redirect("tcp", dest),
|
||||
redirect("udp", udpDest),
|
||||
},
|
||||
}
|
||||
|
||||
clientPort := tcp.PickPort()
|
||||
client6Port := tcp.PickPort()
|
||||
clientUDPPort := udp.PickPort()
|
||||
dokodemoInbound := func(port net.Port, dest net.Destination) *core.InboundHandlerConfig {
|
||||
return &core.InboundHandlerConfig{
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(port)}},
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
|
||||
RewriteAddress: net.NewIPOrDomain(dest.Address),
|
||||
RewritePort: uint32(dest.Port),
|
||||
AllowedNetworks: []net.Network{dest.Network},
|
||||
}),
|
||||
}
|
||||
}
|
||||
clientConfig := &core.Config{
|
||||
App: []*serial.TypedMessage{
|
||||
serial.ToTypedMessage(&log.Config{
|
||||
ErrorLogLevel: clog.Severity_Debug,
|
||||
ErrorLogLevel: clog.Severity_Warning,
|
||||
ErrorLogType: log.LogType_Console,
|
||||
}),
|
||||
},
|
||||
Inbound: []*core.InboundHandlerConfig{
|
||||
{
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(clientPort)}},
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
|
||||
RewriteAddress: net.NewIPOrDomain(dest.Address),
|
||||
RewritePort: uint32(dest.Port),
|
||||
AllowedNetworks: []net.Network{net.Network_TCP},
|
||||
}),
|
||||
},
|
||||
dokodemoInbound(clientPort, net.TCPDestination(net.ParseAddress("192.0.2.1"), 7)),
|
||||
dokodemoInbound(client6Port, net.TCPDestination(net.ParseAddress("2001:db8::1"), 7)),
|
||||
dokodemoInbound(clientUDPPort, net.UDPDestination(net.ParseAddress("192.0.2.1"), 7)),
|
||||
},
|
||||
Outbound: []*core.OutboundHandlerConfig{
|
||||
{
|
||||
ProxySettings: serial.ToTypedMessage(&wireguard.DeviceConfig{
|
||||
IsClient: true,
|
||||
NoKernelTun: false,
|
||||
Endpoint: []string{"10.0.0.2"},
|
||||
NoKernelTun: true,
|
||||
Endpoint: []string{"10.0.0.2", "fd00::2"},
|
||||
Mtu: 1420,
|
||||
SecretKey: clientPrivate,
|
||||
Peers: []*wireguard.PeerConfig{{
|
||||
Endpoint: "127.0.0.1:" + serverPort.String(),
|
||||
PublicKey: clientPublic,
|
||||
PublicKey: wireguardPublicKey(serverPrivate),
|
||||
AllowedIps: []string{"0.0.0.0/0", "::0/0"},
|
||||
}},
|
||||
}),
|
||||
@@ -114,13 +157,13 @@ func TestWireguard(t *testing.T) {
|
||||
common.Must(err)
|
||||
defer CloseAllServers(servers)
|
||||
|
||||
// FIXME: for some reason wg server does not receive
|
||||
|
||||
// var errg errgroup.Group
|
||||
// for i := 0; i < 1; i++ {
|
||||
// errg.Go(testTCPConn(clientPort, 1024, time.Second*2))
|
||||
// }
|
||||
// if err := errg.Wait(); err != nil {
|
||||
// t.Error(err)
|
||||
// }
|
||||
var errg errgroup.Group
|
||||
for range 3 {
|
||||
errg.Go(testTCPConn(clientPort, 1024*1024, time.Second*20))
|
||||
}
|
||||
errg.Go(testTCPConn(client6Port, 1024*1024, time.Second*20))
|
||||
errg.Go(testUDPConn(clientUDPPort, 1024, time.Second*5))
|
||||
if err := errg.Wait(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user