Compare commits
9 Commits
v1.3-beta8
...
v1.2.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90c54c1a38 | ||
|
|
0dd19ac0f3 | ||
|
|
1f65ff88b5 | ||
|
|
bbdd495ed5 | ||
|
|
d686172854 | ||
|
|
e1d96cb64e | ||
|
|
d5f94b65b7 | ||
|
|
ec2d0b6b3c | ||
|
|
3a92bf993d |
@@ -1,3 +1,7 @@
|
|||||||
|
#### 1.2.5
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
#### 1.2.4
|
#### 1.2.4
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type PlatformInterface interface {
|
type PlatformInterface interface {
|
||||||
|
UsePlatformAutoDetectInterfaceControl() bool
|
||||||
AutoDetectInterfaceControl(fd int32) error
|
AutoDetectInterfaceControl(fd int32) error
|
||||||
OpenTun(options TunOptions) (int32, error)
|
OpenTun(options TunOptions) (int32, error)
|
||||||
WriteLog(message string)
|
WriteLog(message string)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
|
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
Initialize(ctx context.Context, router adapter.Router) error
|
Initialize(ctx context.Context, router adapter.Router) error
|
||||||
|
UsePlatformAutoDetectInterfaceControl() bool
|
||||||
AutoDetectInterfaceControl() control.Func
|
AutoDetectInterfaceControl() control.Func
|
||||||
OpenTun(options *tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error)
|
OpenTun(options *tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error)
|
||||||
UsePlatformDefaultInterfaceMonitor() bool
|
UsePlatformDefaultInterfaceMonitor() bool
|
||||||
|
|||||||
@@ -68,6 +68,10 @@ func (w *platformInterfaceWrapper) Initialize(ctx context.Context, router adapte
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *platformInterfaceWrapper) UsePlatformAutoDetectInterfaceControl() bool {
|
||||||
|
return w.iif.UsePlatformAutoDetectInterfaceControl()
|
||||||
|
}
|
||||||
|
|
||||||
func (w *platformInterfaceWrapper) AutoDetectInterfaceControl() control.Func {
|
func (w *platformInterfaceWrapper) AutoDetectInterfaceControl() control.Func {
|
||||||
return func(network, address string, conn syscall.RawConn) error {
|
return func(network, address string, conn syscall.RawConn) error {
|
||||||
return control.Raw(conn, func(fd uintptr) error {
|
return control.Raw(conn, func(fd uintptr) error {
|
||||||
|
|||||||
@@ -90,6 +90,9 @@ func (n *Naive) Start() error {
|
|||||||
n.httpServer = &http.Server{
|
n.httpServer = &http.Server{
|
||||||
Handler: n,
|
Handler: n,
|
||||||
TLSConfig: tlsConfig,
|
TLSConfig: tlsConfig,
|
||||||
|
BaseContext: func(listener net.Listener) context.Context {
|
||||||
|
return n.ctx
|
||||||
|
},
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
var sErr error
|
var sErr error
|
||||||
|
|||||||
@@ -823,7 +823,7 @@ func (r *Router) AutoDetectInterface() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) AutoDetectInterfaceFunc() control.Func {
|
func (r *Router) AutoDetectInterfaceFunc() control.Func {
|
||||||
if r.platformInterface != nil {
|
if r.platformInterface != nil && r.platformInterface.UsePlatformAutoDetectInterfaceControl() {
|
||||||
return r.platformInterface.AutoDetectInterfaceControl()
|
return r.platformInterface.AutoDetectInterfaceControl()
|
||||||
} else {
|
} else {
|
||||||
return control.BindToInterfaceFunc(r.InterfaceFinder(), func(network string, address string) (interfaceName string, interfaceIndex int) {
|
return control.BindToInterfaceFunc(r.InterfaceFinder(), func(network string, address string) (interfaceName string, interfaceIndex int) {
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ func newV2RayPlugin(pluginOpts Args, router adapter.Router, dialer N.Dialer, ser
|
|||||||
|
|
||||||
if hostOpt, loaded := pluginOpts.Get("host"); loaded {
|
if hostOpt, loaded := pluginOpts.Get("host"); loaded {
|
||||||
host = hostOpt
|
host = hostOpt
|
||||||
|
tlsOptions.ServerName = hostOpt
|
||||||
}
|
}
|
||||||
if pathOpt, loaded := pluginOpts.Get("path"); loaded {
|
if pathOpt, loaded := pluginOpts.Get("path"); loaded {
|
||||||
path = pathOpt
|
path = pathOpt
|
||||||
|
|||||||
@@ -48,9 +48,6 @@ func NewClientTransport(ctx context.Context, dialer N.Dialer, serverAddr M.Socks
|
|||||||
case C.V2RayTransportTypeHTTP:
|
case C.V2RayTransportTypeHTTP:
|
||||||
return v2rayhttp.NewClient(ctx, dialer, serverAddr, options.HTTPOptions, tlsConfig)
|
return v2rayhttp.NewClient(ctx, dialer, serverAddr, options.HTTPOptions, tlsConfig)
|
||||||
case C.V2RayTransportTypeGRPC:
|
case C.V2RayTransportTypeGRPC:
|
||||||
if tlsConfig == nil {
|
|
||||||
return nil, C.ErrTLSRequired
|
|
||||||
}
|
|
||||||
return NewGRPCClient(ctx, dialer, serverAddr, options.GRPCOptions, tlsConfig)
|
return NewGRPCClient(ctx, dialer, serverAddr, options.GRPCOptions, tlsConfig)
|
||||||
case C.V2RayTransportTypeWebsocket:
|
case C.V2RayTransportTypeWebsocket:
|
||||||
return v2raywebsocket.NewClient(ctx, dialer, serverAddr, options.WebsocketOptions, tlsConfig), nil
|
return v2raywebsocket.NewClient(ctx, dialer, serverAddr, options.WebsocketOptions, tlsConfig), nil
|
||||||
|
|||||||
@@ -36,7 +36,9 @@ type Client struct {
|
|||||||
func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayGRPCOptions, tlsConfig tls.Config) (adapter.V2RayClientTransport, error) {
|
func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayGRPCOptions, tlsConfig tls.Config) (adapter.V2RayClientTransport, error) {
|
||||||
var dialOptions []grpc.DialOption
|
var dialOptions []grpc.DialOption
|
||||||
if tlsConfig != nil {
|
if tlsConfig != nil {
|
||||||
tlsConfig.SetNextProtos([]string{http2.NextProtoTLS})
|
if len(tlsConfig.NextProtos()) == 0 {
|
||||||
|
tlsConfig.SetNextProtos([]string{http2.NextProtoTLS})
|
||||||
|
}
|
||||||
dialOptions = append(dialOptions, grpc.WithTransportCredentials(NewTLSTransportCredentials(tlsConfig)))
|
dialOptions = append(dialOptions, grpc.WithTransportCredentials(NewTLSTransportCredentials(tlsConfig)))
|
||||||
} else {
|
} else {
|
||||||
dialOptions = append(dialOptions, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
dialOptions = append(dialOptions, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package v2raygrpclite
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -13,6 +12,7 @@ import (
|
|||||||
"github.com/sagernet/sing-box/common/tls"
|
"github.com/sagernet/sing-box/common/tls"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing-box/transport/v2rayhttp"
|
"github.com/sagernet/sing-box/transport/v2rayhttp"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
|
||||||
@@ -31,56 +31,63 @@ type Client struct {
|
|||||||
ctx context.Context
|
ctx context.Context
|
||||||
dialer N.Dialer
|
dialer N.Dialer
|
||||||
serverAddr M.Socksaddr
|
serverAddr M.Socksaddr
|
||||||
transport http.RoundTripper
|
transport *http2.Transport
|
||||||
options option.V2RayGRPCOptions
|
options option.V2RayGRPCOptions
|
||||||
url *url.URL
|
url *url.URL
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayGRPCOptions, tlsConfig tls.Config) adapter.V2RayClientTransport {
|
func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayGRPCOptions, tlsConfig tls.Config) adapter.V2RayClientTransport {
|
||||||
var transport http.RoundTripper
|
var host string
|
||||||
if tlsConfig == nil {
|
if tlsConfig != nil && tlsConfig.ServerName() != "" {
|
||||||
transport = &http.Transport{
|
host = M.ParseSocksaddrHostPort(tlsConfig.ServerName(), serverAddr.Port).String()
|
||||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
||||||
return dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
tlsConfig.SetNextProtos([]string{http2.NextProtoTLS})
|
host = serverAddr.String()
|
||||||
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 {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return tls.ClientHandshake(ctx, conn, tlsConfig)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return &Client{
|
client := &Client{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
dialer: dialer,
|
dialer: dialer,
|
||||||
serverAddr: serverAddr,
|
serverAddr: serverAddr,
|
||||||
options: options,
|
options: options,
|
||||||
transport: transport,
|
transport: &http2.Transport{
|
||||||
|
ReadIdleTimeout: time.Duration(options.IdleTimeout),
|
||||||
|
PingTimeout: time.Duration(options.PingTimeout),
|
||||||
|
DisableCompression: true,
|
||||||
|
},
|
||||||
url: &url.URL{
|
url: &url.URL{
|
||||||
Scheme: "https",
|
Scheme: "https",
|
||||||
Host: serverAddr.String(),
|
Host: host,
|
||||||
Path: fmt.Sprintf("/%s/Tun", url.QueryEscape(options.ServiceName)),
|
Path: "/" + options.ServiceName + "/Tun",
|
||||||
|
RawPath: "/" + url.PathEscape(options.ServiceName) + "/Tun",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if tlsConfig == nil {
|
||||||
|
client.transport.DialTLSContext = func(ctx context.Context, network, addr string, cfg *tls.STDConfig) (net.Conn, error) {
|
||||||
|
return dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if len(tlsConfig.NextProtos()) == 0 {
|
||||||
|
tlsConfig.SetNextProtos([]string{http2.NextProtoTLS})
|
||||||
|
}
|
||||||
|
client.transport.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 {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return tls.ClientHandshake(ctx, conn, tlsConfig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
|
func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
|
||||||
pipeInReader, pipeInWriter := io.Pipe()
|
pipeInReader, pipeInWriter := io.Pipe()
|
||||||
request := &http.Request{
|
request := &http.Request{
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
Body: pipeInReader,
|
Body: pipeInReader,
|
||||||
URL: c.url,
|
URL: c.url,
|
||||||
Proto: "HTTP/2",
|
Header: defaultClientHeader,
|
||||||
ProtoMajor: 2,
|
|
||||||
Header: defaultClientHeader,
|
|
||||||
}
|
}
|
||||||
request = request.WithContext(ctx)
|
request = request.WithContext(ctx)
|
||||||
conn := newLateGunConn(pipeInWriter)
|
conn := newLateGunConn(pipeInWriter)
|
||||||
@@ -88,6 +95,9 @@ func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
|
|||||||
response, err := c.transport.RoundTrip(request)
|
response, err := c.transport.RoundTrip(request)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
conn.setup(response.Body, nil)
|
conn.setup(response.Body, nil)
|
||||||
|
} else if response.StatusCode != 200 {
|
||||||
|
response.Body.Close()
|
||||||
|
conn.setup(nil, E.New("unexpected status: ", response.StatusCode, " ", response.Status))
|
||||||
} else {
|
} else {
|
||||||
conn.setup(nil, err)
|
conn.setup(nil, err)
|
||||||
}
|
}
|
||||||
@@ -96,6 +106,8 @@ func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Close() error {
|
func (c *Client) Close() error {
|
||||||
v2rayhttp.CloseIdleConnections(c.transport)
|
if c.transport != nil {
|
||||||
|
v2rayhttp.CloseIdleConnections(c.transport)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ func (c *GunConn) WriteBuffer(buffer *buf.Buffer) error {
|
|||||||
dataLen := buffer.Len()
|
dataLen := buffer.Len()
|
||||||
varLen := rw.UVariantLen(uint64(dataLen))
|
varLen := rw.UVariantLen(uint64(dataLen))
|
||||||
header := buffer.ExtendHeader(6 + varLen)
|
header := buffer.ExtendHeader(6 + varLen)
|
||||||
|
_ = header[6]
|
||||||
header[0] = 0x00
|
header[0] = 0x00
|
||||||
binary.BigEndian.PutUint32(header[1:5], uint32(1+varLen+dataLen))
|
binary.BigEndian.PutUint32(header[1:5], uint32(1+varLen+dataLen))
|
||||||
header[5] = 0x0A
|
header[5] = 0x0A
|
||||||
|
|||||||
@@ -2,10 +2,8 @@ package v2raygrpclite
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -45,13 +43,16 @@ func NewServer(ctx context.Context, options option.V2RayGRPCOptions, tlsConfig t
|
|||||||
server := &Server{
|
server := &Server{
|
||||||
tlsConfig: tlsConfig,
|
tlsConfig: tlsConfig,
|
||||||
handler: handler,
|
handler: handler,
|
||||||
path: fmt.Sprintf("/%s/Tun", url.QueryEscape(options.ServiceName)),
|
path: "/" + options.ServiceName + "/Tun",
|
||||||
h2Server: &http2.Server{
|
h2Server: &http2.Server{
|
||||||
IdleTimeout: time.Duration(options.IdleTimeout),
|
IdleTimeout: time.Duration(options.IdleTimeout),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
server.httpServer = &http.Server{
|
server.httpServer = &http.Server{
|
||||||
Handler: server,
|
Handler: server,
|
||||||
|
BaseContext: func(net.Listener) context.Context {
|
||||||
|
return ctx
|
||||||
|
},
|
||||||
}
|
}
|
||||||
server.h2cHandler = h2c.NewHandler(server, server.h2Server)
|
server.h2cHandler = h2c.NewHandler(server, server.h2Server)
|
||||||
return server, nil
|
return server, nil
|
||||||
|
|||||||
@@ -43,7 +43,9 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tlsConfig.SetNextProtos([]string{http2.NextProtoTLS})
|
if len(tlsConfig.NextProtos()) == 0 {
|
||||||
|
tlsConfig.SetNextProtos([]string{http2.NextProtoTLS})
|
||||||
|
}
|
||||||
transport = &http2.Transport{
|
transport = &http2.Transport{
|
||||||
ReadIdleTimeout: time.Duration(options.IdleTimeout),
|
ReadIdleTimeout: time.Duration(options.IdleTimeout),
|
||||||
PingTimeout: time.Duration(options.PingTimeout),
|
PingTimeout: time.Duration(options.PingTimeout),
|
||||||
@@ -137,15 +139,16 @@ func (c *Client) dialHTTP2(ctx context.Context) (net.Conn, error) {
|
|||||||
default:
|
default:
|
||||||
request.Host = c.host[rand.Intn(hostLen)]
|
request.Host = c.host[rand.Intn(hostLen)]
|
||||||
}
|
}
|
||||||
conn := newLateHTTPConn(pipeInWriter)
|
conn := NewLateHTTPConn(pipeInWriter)
|
||||||
go func() {
|
go func() {
|
||||||
response, err := c.transport.RoundTrip(request)
|
response, err := c.transport.RoundTrip(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
conn.setup(nil, err)
|
conn.Setup(nil, err)
|
||||||
} else if response.StatusCode != 200 {
|
} else if response.StatusCode != 200 {
|
||||||
conn.setup(nil, E.New("unexpected status: ", response.StatusCode, " ", response.Status))
|
response.Body.Close()
|
||||||
|
conn.Setup(nil, E.New("unexpected status: ", response.StatusCode, " ", response.Status))
|
||||||
} else {
|
} else {
|
||||||
conn.setup(response.Body, nil)
|
conn.Setup(response.Body, nil)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return conn, nil
|
return conn, nil
|
||||||
|
|||||||
@@ -140,14 +140,14 @@ func NewHTTPConn(reader io.Reader, writer io.Writer) HTTP2Conn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newLateHTTPConn(writer io.Writer) *HTTP2Conn {
|
func NewLateHTTPConn(writer io.Writer) *HTTP2Conn {
|
||||||
return &HTTP2Conn{
|
return &HTTP2Conn{
|
||||||
create: make(chan struct{}),
|
create: make(chan struct{}),
|
||||||
writer: writer,
|
writer: writer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *HTTP2Conn) setup(reader io.Reader, err error) {
|
func (c *HTTP2Conn) Setup(reader io.Reader, err error) {
|
||||||
c.reader = reader
|
c.reader = reader
|
||||||
c.err = err
|
c.err = err
|
||||||
close(c.create)
|
close(c.create)
|
||||||
|
|||||||
@@ -70,6 +70,9 @@ func NewServer(ctx context.Context, options option.V2RayHTTPOptions, tlsConfig t
|
|||||||
Handler: server,
|
Handler: server,
|
||||||
ReadHeaderTimeout: C.TCPTimeout,
|
ReadHeaderTimeout: C.TCPTimeout,
|
||||||
MaxHeaderBytes: http.DefaultMaxHeaderBytes,
|
MaxHeaderBytes: http.DefaultMaxHeaderBytes,
|
||||||
|
BaseContext: func(net.Listener) context.Context {
|
||||||
|
return ctx
|
||||||
|
},
|
||||||
}
|
}
|
||||||
server.h2cHandler = h2c.NewHandler(server, server.h2Server)
|
server.h2cHandler = h2c.NewHandler(server, server.h2Server)
|
||||||
return server, nil
|
return server, nil
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ func NewServer(ctx context.Context, options option.V2RayWebsocketOptions, tlsCon
|
|||||||
Handler: server,
|
Handler: server,
|
||||||
ReadHeaderTimeout: C.TCPTimeout,
|
ReadHeaderTimeout: C.TCPTimeout,
|
||||||
MaxHeaderBytes: http.DefaultMaxHeaderBytes,
|
MaxHeaderBytes: http.DefaultMaxHeaderBytes,
|
||||||
|
BaseContext: func(net.Listener) context.Context {
|
||||||
|
return ctx
|
||||||
|
},
|
||||||
}
|
}
|
||||||
return server, nil
|
return server, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user