Add health check support for http-based v2ray transport

This commit is contained in:
世界 2023-03-11 15:49:02 +08:00
parent bdc620dab1
commit 6af9c2b3ca
No known key found for this signature in database
GPG Key ID: CD109927C34A63C4
7 changed files with 45 additions and 12 deletions

View File

@ -61,10 +61,12 @@ func (o *V2RayTransportOptions) UnmarshalJSON(bytes []byte) error {
}
type V2RayHTTPOptions struct {
Host Listable[string] `json:"host,omitempty"`
Path string `json:"path,omitempty"`
Method string `json:"method,omitempty"`
Headers map[string]string `json:"headers,omitempty"`
Host Listable[string] `json:"host,omitempty"`
Path string `json:"path,omitempty"`
Method string `json:"method,omitempty"`
Headers map[string]string `json:"headers,omitempty"`
IdleTimeout Duration `json:"idle_timeout,omitempty"`
PingTimeout Duration `json:"ping_timeout,omitempty"`
}
type V2RayWebsocketOptions struct {
@ -77,6 +79,9 @@ type V2RayWebsocketOptions struct {
type V2RayQUICOptions struct{}
type V2RayGRPCOptions struct {
ServiceName string `json:"service_name,omitempty"`
ForceLite bool `json:"-"` // for test
ServiceName string `json:"service_name,omitempty"`
IdleTimeout Duration `json:"idle_timeout,omitempty"`
PingTimeout Duration `json:"ping_timeout,omitempty"`
PermitWithoutStream bool `json:"permit_without_stream,omitempty"`
ForceLite bool `json:"-"` // for test
}

View File

@ -18,6 +18,7 @@ import (
"google.golang.org/grpc/backoff"
"google.golang.org/grpc/connectivity"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/keepalive"
)
var _ adapter.V2RayClientTransport = (*Client)(nil)
@ -40,6 +41,13 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
} else {
dialOptions = append(dialOptions, grpc.WithTransportCredentials(insecure.NewCredentials()))
}
if options.IdleTimeout > 0 {
dialOptions = append(dialOptions, grpc.WithKeepaliveParams(keepalive.ClientParameters{
Time: time.Duration(options.IdleTimeout),
Timeout: time.Duration(options.PingTimeout),
PermitWithoutStream: options.PermitWithoutStream,
}))
}
dialOptions = append(dialOptions, grpc.WithConnectParams(grpc.ConnectParams{
Backoff: backoff.Config{
BaseDelay: 500 * time.Millisecond,

View File

@ -5,6 +5,7 @@ import (
"net"
"os"
"strings"
"time"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/tls"
@ -13,6 +14,7 @@ import (
N "github.com/sagernet/sing/common/network"
"google.golang.org/grpc"
"google.golang.org/grpc/keepalive"
gM "google.golang.org/grpc/metadata"
"google.golang.org/grpc/peer"
)
@ -31,6 +33,12 @@ func NewServer(ctx context.Context, options option.V2RayGRPCOptions, tlsConfig t
tlsConfig.SetNextProtos([]string{"h2"})
serverOptions = append(serverOptions, grpc.Creds(NewTLSTransportCredentials(tlsConfig)))
}
if options.IdleTimeout > 0 {
serverOptions = append(serverOptions, grpc.KeepaliveParams(keepalive.ServerParameters{
Time: time.Duration(options.IdleTimeout),
Timeout: time.Duration(options.PingTimeout),
}))
}
server := &Server{ctx, handler, grpc.NewServer(serverOptions...)}
RegisterGunServiceCustomNameServer(server.server, server, options.ServiceName)
return server, nil

View File

@ -7,6 +7,7 @@ import (
"net"
"net/http"
"net/url"
"time"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/tls"
@ -45,6 +46,8 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
} else {
tlsConfig.SetNextProtos([]string{http2.NextProtoTLS})
transport = &http2.Transport{
ReadIdleTimeout: time.Duration(options.IdleTimeout),
PingTimeout: time.Duration(options.PingTimeout),
DialTLSContext: func(ctx context.Context, network, addr string, cfg *tls.STDConfig) (net.Conn, error) {
conn, err := dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
if err != nil {

View File

@ -8,6 +8,7 @@ import (
"net/url"
"os"
"strings"
"time"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/tls"
@ -45,7 +46,9 @@ func NewServer(ctx context.Context, options option.V2RayGRPCOptions, tlsConfig t
tlsConfig: tlsConfig,
handler: handler,
path: fmt.Sprintf("/%s/Tun", url.QueryEscape(options.ServiceName)),
h2Server: new(http2.Server),
h2Server: &http2.Server{
IdleTimeout: time.Duration(options.IdleTimeout),
},
}
server.httpServer = &http.Server{
Handler: server,

View File

@ -9,6 +9,7 @@ import (
"net/http"
"net/url"
"strings"
"time"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/tls"
@ -45,6 +46,8 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
} else {
tlsConfig.SetNextProtos([]string{http2.NextProtoTLS})
transport = &http2.Transport{
ReadIdleTimeout: time.Duration(options.IdleTimeout),
PingTimeout: time.Duration(options.PingTimeout),
DialTLSContext: func(ctx context.Context, network, addr string, cfg *tls.STDConfig) (net.Conn, error) {
conn, err := dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
if err != nil {

View File

@ -6,6 +6,7 @@ import (
"net/http"
"os"
"strings"
"time"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/tls"
@ -46,11 +47,13 @@ func NewServer(ctx context.Context, options option.V2RayHTTPOptions, tlsConfig t
ctx: ctx,
tlsConfig: tlsConfig,
handler: handler,
h2Server: new(http2.Server),
host: options.Host,
path: options.Path,
method: options.Method,
headers: make(http.Header),
h2Server: &http2.Server{
IdleTimeout: time.Duration(options.IdleTimeout),
},
host: options.Host,
path: options.Path,
method: options.Method,
headers: make(http.Header),
}
if server.method == "" {
server.method = "PUT"