Refactor OpenVPN and OpenConnect endpoints

This commit is contained in:
世界
2026-07-18 09:40:17 +08:00
parent 60f3012444
commit a4367df680
25 changed files with 758 additions and 182 deletions
+44 -5
View File
@@ -21,6 +21,7 @@ import (
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/option"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/json/badoption"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
@@ -125,6 +126,8 @@ func TestOpenConnectDockerInterop(t *testing.T) {
require.Nil(subtest, status.AuthForm)
err := exchangeOpenConnectTCPEcho(endpoint, 256*1024, 30*time.Second)
require.NoError(subtest, err)
err = exchangeOpenConnectUDPEcho(endpoint, 1400, 30*time.Second)
require.NoError(subtest, err)
})
t.Run("interactive_password_auth", func(subtest *testing.T) {
@@ -174,11 +177,15 @@ func TestOpenConnectDockerInterop(t *testing.T) {
func openConnectInstanceOptions(server string, certificateAuthorityPath string, username string, password string) option.Options {
endpointOptions := option.OpenConnectEndpointOptions{
Server: server,
Flavor: "anyconnect",
Username: username,
Password: password,
NoUDP: true,
Server: server,
Flavor: "anyconnect",
Username: username,
Password: password,
NoUDP: true,
UDPTimeout: badoption.Duration(time.Minute),
UDPMapping: option.UDPNATBehaviorAddressDependent,
UDPFiltering: option.UDPNATBehaviorAddressAndPortDependent,
UDPNATMax: 128,
TLS: option.OpenConnectTLSOptions{
CertificateAuthorityPath: certificateAuthorityPath,
},
@@ -318,6 +325,38 @@ func exchangeOpenConnectTCPEcho(endpoint adapter.OpenConnectEndpoint, payloadSiz
return nil
}
func exchangeOpenConnectUDPEcho(endpoint adapter.OpenConnectEndpoint, payloadSize int, timeout time.Duration) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
conn, err := endpoint.DialContext(ctx, N.NetworkUDP, M.ParseSocksaddrHostPort(openConnectTunnelAddress, openConnectEchoPort))
if err != nil {
return E.Cause(err, "dial ocserv tunnel UDP echo")
}
defer conn.Close()
err = conn.SetDeadline(time.Now().Add(timeout))
if err != nil {
return E.Cause(err, "set ocserv tunnel UDP echo deadline")
}
payload := make([]byte, payloadSize)
_, err = rand.Read(payload)
if err != nil {
return E.Cause(err, "generate ocserv tunnel UDP echo payload")
}
_, err = conn.Write(payload)
if err != nil {
return E.Cause(err, "write ocserv tunnel UDP echo payload")
}
response := make([]byte, payloadSize+1)
responseLength, err := conn.Read(response)
if err != nil {
return E.Cause(err, "read ocserv tunnel UDP echo payload")
}
if !bytes.Equal(response[:responseLength], payload) {
return E.New("ocserv tunnel UDP echo payload mismatch")
}
return nil
}
func waitForOpenConnectTCPEcho(t *testing.T, endpoint adapter.OpenConnectEndpoint, timeout time.Duration) {
t.Helper()
deadline := time.Now().Add(timeout)