mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-22 08:31:30 +00:00
Add health check support for http-based v2ray transport
This commit is contained in:
parent
bdc620dab1
commit
6af9c2b3ca
|
@ -61,10 +61,12 @@ func (o *V2RayTransportOptions) UnmarshalJSON(bytes []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
type V2RayHTTPOptions struct {
|
type V2RayHTTPOptions struct {
|
||||||
Host Listable[string] `json:"host,omitempty"`
|
Host Listable[string] `json:"host,omitempty"`
|
||||||
Path string `json:"path,omitempty"`
|
Path string `json:"path,omitempty"`
|
||||||
Method string `json:"method,omitempty"`
|
Method string `json:"method,omitempty"`
|
||||||
Headers map[string]string `json:"headers,omitempty"`
|
Headers map[string]string `json:"headers,omitempty"`
|
||||||
|
IdleTimeout Duration `json:"idle_timeout,omitempty"`
|
||||||
|
PingTimeout Duration `json:"ping_timeout,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type V2RayWebsocketOptions struct {
|
type V2RayWebsocketOptions struct {
|
||||||
|
@ -77,6 +79,9 @@ type V2RayWebsocketOptions struct {
|
||||||
type V2RayQUICOptions struct{}
|
type V2RayQUICOptions struct{}
|
||||||
|
|
||||||
type V2RayGRPCOptions struct {
|
type V2RayGRPCOptions struct {
|
||||||
ServiceName string `json:"service_name,omitempty"`
|
ServiceName string `json:"service_name,omitempty"`
|
||||||
ForceLite bool `json:"-"` // for test
|
IdleTimeout Duration `json:"idle_timeout,omitempty"`
|
||||||
|
PingTimeout Duration `json:"ping_timeout,omitempty"`
|
||||||
|
PermitWithoutStream bool `json:"permit_without_stream,omitempty"`
|
||||||
|
ForceLite bool `json:"-"` // for test
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"google.golang.org/grpc/backoff"
|
"google.golang.org/grpc/backoff"
|
||||||
"google.golang.org/grpc/connectivity"
|
"google.golang.org/grpc/connectivity"
|
||||||
"google.golang.org/grpc/credentials/insecure"
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
|
"google.golang.org/grpc/keepalive"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ adapter.V2RayClientTransport = (*Client)(nil)
|
var _ adapter.V2RayClientTransport = (*Client)(nil)
|
||||||
|
@ -40,6 +41,13 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
|
||||||
} else {
|
} else {
|
||||||
dialOptions = append(dialOptions, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
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{
|
dialOptions = append(dialOptions, grpc.WithConnectParams(grpc.ConnectParams{
|
||||||
Backoff: backoff.Config{
|
Backoff: backoff.Config{
|
||||||
BaseDelay: 500 * time.Millisecond,
|
BaseDelay: 500 * time.Millisecond,
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/common/tls"
|
"github.com/sagernet/sing-box/common/tls"
|
||||||
|
@ -13,6 +14,7 @@ import (
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/keepalive"
|
||||||
gM "google.golang.org/grpc/metadata"
|
gM "google.golang.org/grpc/metadata"
|
||||||
"google.golang.org/grpc/peer"
|
"google.golang.org/grpc/peer"
|
||||||
)
|
)
|
||||||
|
@ -31,6 +33,12 @@ func NewServer(ctx context.Context, options option.V2RayGRPCOptions, tlsConfig t
|
||||||
tlsConfig.SetNextProtos([]string{"h2"})
|
tlsConfig.SetNextProtos([]string{"h2"})
|
||||||
serverOptions = append(serverOptions, grpc.Creds(NewTLSTransportCredentials(tlsConfig)))
|
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...)}
|
server := &Server{ctx, handler, grpc.NewServer(serverOptions...)}
|
||||||
RegisterGunServiceCustomNameServer(server.server, server, options.ServiceName)
|
RegisterGunServiceCustomNameServer(server.server, server, options.ServiceName)
|
||||||
return server, nil
|
return server, nil
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/common/tls"
|
"github.com/sagernet/sing-box/common/tls"
|
||||||
|
@ -45,6 +46,8 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
|
||||||
} else {
|
} else {
|
||||||
tlsConfig.SetNextProtos([]string{http2.NextProtoTLS})
|
tlsConfig.SetNextProtos([]string{http2.NextProtoTLS})
|
||||||
transport = &http2.Transport{
|
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) {
|
DialTLSContext: func(ctx context.Context, network, addr string, cfg *tls.STDConfig) (net.Conn, error) {
|
||||||
conn, err := dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
conn, err := dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/common/tls"
|
"github.com/sagernet/sing-box/common/tls"
|
||||||
|
@ -45,7 +46,9 @@ func NewServer(ctx context.Context, options option.V2RayGRPCOptions, tlsConfig t
|
||||||
tlsConfig: tlsConfig,
|
tlsConfig: tlsConfig,
|
||||||
handler: handler,
|
handler: handler,
|
||||||
path: fmt.Sprintf("/%s/Tun", url.QueryEscape(options.ServiceName)),
|
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{
|
server.httpServer = &http.Server{
|
||||||
Handler: server,
|
Handler: server,
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/common/tls"
|
"github.com/sagernet/sing-box/common/tls"
|
||||||
|
@ -45,6 +46,8 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
|
||||||
} else {
|
} else {
|
||||||
tlsConfig.SetNextProtos([]string{http2.NextProtoTLS})
|
tlsConfig.SetNextProtos([]string{http2.NextProtoTLS})
|
||||||
transport = &http2.Transport{
|
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) {
|
DialTLSContext: func(ctx context.Context, network, addr string, cfg *tls.STDConfig) (net.Conn, error) {
|
||||||
conn, err := dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
conn, err := dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/common/tls"
|
"github.com/sagernet/sing-box/common/tls"
|
||||||
|
@ -46,11 +47,13 @@ func NewServer(ctx context.Context, options option.V2RayHTTPOptions, tlsConfig t
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
tlsConfig: tlsConfig,
|
tlsConfig: tlsConfig,
|
||||||
handler: handler,
|
handler: handler,
|
||||||
h2Server: new(http2.Server),
|
h2Server: &http2.Server{
|
||||||
host: options.Host,
|
IdleTimeout: time.Duration(options.IdleTimeout),
|
||||||
path: options.Path,
|
},
|
||||||
method: options.Method,
|
host: options.Host,
|
||||||
headers: make(http.Header),
|
path: options.Path,
|
||||||
|
method: options.Method,
|
||||||
|
headers: make(http.Header),
|
||||||
}
|
}
|
||||||
if server.method == "" {
|
if server.method == "" {
|
||||||
server.method = "PUT"
|
server.method = "PUT"
|
||||||
|
|
Loading…
Reference in a new issue