add grpc tunnel

This commit is contained in:
ginuerzh 2022-01-30 20:29:31 +08:00
parent c4e9b35484
commit c6cb681044
17 changed files with 854 additions and 19 deletions

View File

@ -15,6 +15,7 @@ import (
// Register dialers
_ "github.com/go-gost/gost/pkg/dialer/ftcp"
_ "github.com/go-gost/gost/pkg/dialer/grpc"
_ "github.com/go-gost/gost/pkg/dialer/http2"
_ "github.com/go-gost/gost/pkg/dialer/http2/h2"
_ "github.com/go-gost/gost/pkg/dialer/http3"
@ -53,6 +54,7 @@ import (
// Register listeners
_ "github.com/go-gost/gost/pkg/listener/dns"
_ "github.com/go-gost/gost/pkg/listener/ftcp"
_ "github.com/go-gost/gost/pkg/listener/grpc"
_ "github.com/go-gost/gost/pkg/listener/http2"
_ "github.com/go-gost/gost/pkg/listener/http2/h2"
_ "github.com/go-gost/gost/pkg/listener/http3"

14
go.mod
View File

@ -54,14 +54,20 @@ require (
github.com/xtaci/tcpraw v1.2.25
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
golang.org/x/mod v0.4.2 // indirect
golang.org/x/net v0.0.0-20211209124913-491a49abca63
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect
golang.org/x/text v0.3.6 // indirect
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/grpc v1.44.0
gopkg.in/ini.v1 v1.63.2 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.4.0
)
require github.com/marten-seemann/qpack v0.2.1 // indirect
require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/marten-seemann/qpack v0.2.1 // indirect
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350 // indirect
google.golang.org/protobuf v1.27.1 // indirect
)

20
go.sum
View File

@ -70,6 +70,7 @@ github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBT
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
@ -79,7 +80,11 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coreos/go-iptables v0.5.0 h1:mw6SAibtHKZcNzAsOxjoHIG0gy5YFHhypWSSNc6EjbQ=
github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@ -98,6 +103,7 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
@ -176,6 +182,7 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
@ -538,6 +545,8 @@ golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY=
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -633,9 +642,12 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -645,6 +657,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -809,7 +823,10 @@ google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKr
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71 h1:z+ErRPu0+KS02Td3fOAgdX+lnPDh/VyaABEJPD4JRQs=
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350 h1:YxHp5zqIcAShDEvRr5/0rVESVS+njYF68PSdazrNLJo=
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
@ -837,7 +854,10 @@ google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg=
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=

View File

@ -36,7 +36,9 @@ func (tr *Transport) Dial(ctx context.Context, addr string) (net.Conn, error) {
}
func (tr *Transport) dialOptions() []dialer.DialOption {
var opts []dialer.DialOption
opts := []dialer.DialOption{
dialer.HostDialOption(tr.addr),
}
if !tr.route.IsEmpty() {
opts = append(opts,
dialer.DialFuncDialOption(

View File

@ -0,0 +1,148 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc v3.12.4
// source: gost.proto
package proto
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Chunk struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
}
func (x *Chunk) Reset() {
*x = Chunk{}
if protoimpl.UnsafeEnabled {
mi := &file_gost_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Chunk) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Chunk) ProtoMessage() {}
func (x *Chunk) ProtoReflect() protoreflect.Message {
mi := &file_gost_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Chunk.ProtoReflect.Descriptor instead.
func (*Chunk) Descriptor() ([]byte, []int) {
return file_gost_proto_rawDescGZIP(), []int{0}
}
func (x *Chunk) GetData() []byte {
if x != nil {
return x.Data
}
return nil
}
var File_gost_proto protoreflect.FileDescriptor
var file_gost_proto_rawDesc = []byte{
0x0a, 0x0a, 0x67, 0x6f, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x1b, 0x0a, 0x05,
0x43, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, 0x29, 0x0a, 0x09, 0x47, 0x6f, 0x73,
0x74, 0x54, 0x75, 0x6e, 0x65, 0x6c, 0x12, 0x1c, 0x0a, 0x06, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c,
0x12, 0x06, 0x2e, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x1a, 0x06, 0x2e, 0x43, 0x68, 0x75, 0x6e, 0x6b,
0x28, 0x01, 0x30, 0x01, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x2d, 0x67, 0x6f, 0x73, 0x74, 0x2f, 0x67, 0x6f, 0x73, 0x74, 0x2f,
0x70, 0x6b, 0x67, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x75, 0x74, 0x69, 0x6c, 0x2f,
0x67, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
}
var (
file_gost_proto_rawDescOnce sync.Once
file_gost_proto_rawDescData = file_gost_proto_rawDesc
)
func file_gost_proto_rawDescGZIP() []byte {
file_gost_proto_rawDescOnce.Do(func() {
file_gost_proto_rawDescData = protoimpl.X.CompressGZIP(file_gost_proto_rawDescData)
})
return file_gost_proto_rawDescData
}
var file_gost_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_gost_proto_goTypes = []interface{}{
(*Chunk)(nil), // 0: Chunk
}
var file_gost_proto_depIdxs = []int32{
0, // 0: GostTunel.Tunnel:input_type -> Chunk
0, // 1: GostTunel.Tunnel:output_type -> Chunk
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_gost_proto_init() }
func file_gost_proto_init() {
if File_gost_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_gost_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Chunk); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_gost_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_gost_proto_goTypes,
DependencyIndexes: file_gost_proto_depIdxs,
MessageInfos: file_gost_proto_msgTypes,
}.Build()
File_gost_proto = out.File
file_gost_proto_rawDesc = nil
file_gost_proto_goTypes = nil
file_gost_proto_depIdxs = nil
}

View File

@ -0,0 +1,10 @@
syntax = "proto3";
option go_package = "github.com/go-gost/gost/pkg/common/util/grpc/proto";
message Chunk {
bytes data = 1;
}
service GostTunel {
rpc Tunnel (stream Chunk) returns (stream Chunk);
}

View File

@ -0,0 +1,133 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
package proto
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// GostTunelClient is the client API for GostTunel service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type GostTunelClient interface {
Tunnel(ctx context.Context, opts ...grpc.CallOption) (GostTunel_TunnelClient, error)
}
type gostTunelClient struct {
cc grpc.ClientConnInterface
}
func NewGostTunelClient(cc grpc.ClientConnInterface) GostTunelClient {
return &gostTunelClient{cc}
}
func (c *gostTunelClient) Tunnel(ctx context.Context, opts ...grpc.CallOption) (GostTunel_TunnelClient, error) {
stream, err := c.cc.NewStream(ctx, &GostTunel_ServiceDesc.Streams[0], "/GostTunel/Tunnel", opts...)
if err != nil {
return nil, err
}
x := &gostTunelTunnelClient{stream}
return x, nil
}
type GostTunel_TunnelClient interface {
Send(*Chunk) error
Recv() (*Chunk, error)
grpc.ClientStream
}
type gostTunelTunnelClient struct {
grpc.ClientStream
}
func (x *gostTunelTunnelClient) Send(m *Chunk) error {
return x.ClientStream.SendMsg(m)
}
func (x *gostTunelTunnelClient) Recv() (*Chunk, error) {
m := new(Chunk)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
// GostTunelServer is the server API for GostTunel service.
// All implementations must embed UnimplementedGostTunelServer
// for forward compatibility
type GostTunelServer interface {
Tunnel(GostTunel_TunnelServer) error
mustEmbedUnimplementedGostTunelServer()
}
// UnimplementedGostTunelServer must be embedded to have forward compatible implementations.
type UnimplementedGostTunelServer struct {
}
func (UnimplementedGostTunelServer) Tunnel(GostTunel_TunnelServer) error {
return status.Errorf(codes.Unimplemented, "method Tunnel not implemented")
}
func (UnimplementedGostTunelServer) mustEmbedUnimplementedGostTunelServer() {}
// UnsafeGostTunelServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to GostTunelServer will
// result in compilation errors.
type UnsafeGostTunelServer interface {
mustEmbedUnimplementedGostTunelServer()
}
func RegisterGostTunelServer(s grpc.ServiceRegistrar, srv GostTunelServer) {
s.RegisterService(&GostTunel_ServiceDesc, srv)
}
func _GostTunel_Tunnel_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(GostTunelServer).Tunnel(&gostTunelTunnelServer{stream})
}
type GostTunel_TunnelServer interface {
Send(*Chunk) error
Recv() (*Chunk, error)
grpc.ServerStream
}
type gostTunelTunnelServer struct {
grpc.ServerStream
}
func (x *gostTunelTunnelServer) Send(m *Chunk) error {
return x.ServerStream.SendMsg(m)
}
func (x *gostTunelTunnelServer) Recv() (*Chunk, error) {
m := new(Chunk)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
// GostTunel_ServiceDesc is the grpc.ServiceDesc for GostTunel service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var GostTunel_ServiceDesc = grpc.ServiceDesc{
ServiceName: "GostTunel",
HandlerType: (*GostTunelServer)(nil),
Methods: []grpc.MethodDesc{},
Streams: []grpc.StreamDesc{
{
StreamName: "Tunnel",
Handler: _GostTunel_Tunnel_Handler,
ServerStreams: true,
ClientStreams: true,
},
},
Metadata: "gost.proto",
}

View File

@ -0,0 +1,3 @@
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
gost.proto

92
pkg/dialer/grpc/conn.go Normal file
View File

@ -0,0 +1,92 @@
package grpc
import (
"errors"
"io"
"net"
"time"
pb "github.com/go-gost/gost/pkg/common/util/grpc/proto"
)
type conn struct {
c pb.GostTunel_TunnelClient
rb []byte
localAddr net.Addr
remoteAddr net.Addr
closed chan struct{}
}
func (c *conn) Read(b []byte) (n int, err error) {
select {
case <-c.c.Context().Done():
err = c.c.Context().Err()
return
case <-c.closed:
err = io.ErrClosedPipe
return
default:
}
if len(c.rb) == 0 {
chunk, err := c.c.Recv()
if err != nil {
return 0, err
}
c.rb = chunk.Data
}
n = copy(b, c.rb)
c.rb = c.rb[n:]
return
}
func (c *conn) Write(b []byte) (n int, err error) {
select {
case <-c.c.Context().Done():
err = c.c.Context().Err()
return
case <-c.closed:
err = io.ErrClosedPipe
return
default:
}
if err = c.c.Send(&pb.Chunk{
Data: b,
}); err != nil {
return
}
n = len(b)
return
}
func (c *conn) Close() error {
select {
case <-c.closed:
default:
close(c.closed)
}
return nil
}
func (c *conn) LocalAddr() net.Addr {
return c.localAddr
}
func (c *conn) RemoteAddr() net.Addr {
return c.remoteAddr
}
func (c *conn) SetDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "grpc", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}
func (c *conn) SetReadDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "grpc", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}
func (c *conn) SetWriteDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "grpc", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}

140
pkg/dialer/grpc/dialer.go Normal file
View File

@ -0,0 +1,140 @@
package grpc
import (
"context"
"net"
"sync"
"time"
pb "github.com/go-gost/gost/pkg/common/util/grpc/proto"
"github.com/go-gost/gost/pkg/dialer"
"github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
"google.golang.org/grpc"
"google.golang.org/grpc/backoff"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
)
func init() {
registry.RegisterDialer("grpc", NewDialer)
}
type grpcDialer struct {
clients map[string]pb.GostTunelClient
clientMutex sync.Mutex
logger logger.Logger
md metadata
options dialer.Options
}
func NewDialer(opts ...dialer.Option) dialer.Dialer {
options := dialer.Options{}
for _, opt := range opts {
opt(&options)
}
return &grpcDialer{
clients: make(map[string]pb.GostTunelClient),
logger: options.Logger,
options: options,
}
}
func (d *grpcDialer) Init(md md.Metadata) (err error) {
return d.parseMetadata(md)
}
// Multiplex implements dialer.Multiplexer interface.
func (d *grpcDialer) Multiplex() bool {
return true
}
func (d *grpcDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (net.Conn, error) {
remoteAddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil {
return nil, err
}
d.clientMutex.Lock()
defer d.clientMutex.Unlock()
client, ok := d.clients[addr]
if !ok {
var options dialer.DialOptions
for _, opt := range opts {
opt(&options)
}
host := d.md.host
if host == "" {
host = options.Host
}
grpcOpts := []grpc.DialOption{
grpc.WithBlock(),
grpc.WithContextDialer(func(c context.Context, s string) (net.Conn, error) {
return d.dial(ctx, "tcp", s, &options)
}),
grpc.WithAuthority(host),
grpc.WithConnectParams(grpc.ConnectParams{
Backoff: backoff.DefaultConfig,
MinConnectTimeout: 10 * time.Second,
}),
}
if !d.md.insecure {
grpcOpts = append(grpcOpts, grpc.WithTransportCredentials(credentials.NewTLS(d.options.TLSConfig)))
} else {
grpcOpts = append(grpcOpts, grpc.WithTransportCredentials(insecure.NewCredentials()))
}
cc, err := grpc.DialContext(ctx, addr, grpcOpts...)
if err != nil {
d.logger.Error(err)
return nil, err
}
client = pb.NewGostTunelClient(cc)
d.clients[addr] = client
}
cli, err := client.Tunnel(ctx)
if err != nil {
return nil, err
}
return &conn{
c: cli,
localAddr: &net.TCPAddr{},
remoteAddr: remoteAddr,
closed: make(chan struct{}),
}, nil
}
func (d *grpcDialer) dial(ctx context.Context, network, addr string, opts *dialer.DialOptions) (net.Conn, error) {
dial := opts.DialFunc
if dial != nil {
conn, err := dial(ctx, addr)
if err != nil {
d.logger.Error(err)
} else {
d.logger.WithFields(map[string]interface{}{
"src": conn.LocalAddr().String(),
"dst": addr,
}).Debug("dial with dial func")
}
return conn, err
}
var netd net.Dialer
conn, err := netd.DialContext(ctx, network, addr)
if err != nil {
d.logger.Error(err)
} else {
d.logger.WithFields(map[string]interface{}{
"src": conn.LocalAddr().String(),
"dst": addr,
}).Debugf("dial direct %s/%s", addr, network)
}
return conn, err
}

View File

@ -0,0 +1,22 @@
package grpc
import (
mdata "github.com/go-gost/gost/pkg/metadata"
)
type metadata struct {
insecure bool
host string
}
func (d *grpcDialer) parseMetadata(md mdata.Metadata) (err error) {
const (
insecure = "grpcInsecure"
host = "host"
)
d.md.insecure = mdata.GetBool(md, insecure)
d.md.host = mdata.GetString(md, host)
return
}

View File

@ -53,11 +53,6 @@ func (d *http2Dialer) Multiplex() bool {
}
func (d *http2Dialer) Dial(ctx context.Context, address string, opts ...dialer.DialOption) (net.Conn, error) {
options := &dialer.DialOptions{}
for _, opt := range opts {
opt(options)
}
raddr, err := net.ResolveTCPAddr("tcp", address)
if err != nil {
d.logger.Error(err)
@ -69,11 +64,16 @@ func (d *http2Dialer) Dial(ctx context.Context, address string, opts ...dialer.D
client, ok := d.clients[address]
if !ok {
options := dialer.DialOptions{}
for _, opt := range opts {
opt(&options)
}
client = &http.Client{
Transport: &http.Transport{
TLSClientConfig: d.options.TLSConfig,
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
return d.dial(ctx, network, addr, options)
return d.dial(ctx, network, addr, &options)
},
ForceAttemptHTTP2: true,
MaxIdleConns: 100,

View File

@ -36,11 +36,18 @@ func LoggerOption(logger logger.Logger) Option {
}
type DialOptions struct {
Host string
DialFunc func(ctx context.Context, addr string) (net.Conn, error)
}
type DialOption func(opts *DialOptions)
func HostDialOption(host string) DialOption {
return func(opts *DialOptions) {
opts.Host = host
}
}
func DialFuncDialOption(dialf func(ctx context.Context, addr string) (net.Conn, error)) DialOption {
return func(opts *DialOptions) {
opts.DialFunc = dialf

View File

@ -0,0 +1,101 @@
package grpc
import (
"net"
pb "github.com/go-gost/gost/pkg/common/util/grpc/proto"
"github.com/go-gost/gost/pkg/listener"
"github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
func init() {
registry.RegisterListener("grpc", NewListener)
}
type grpcListener struct {
addr net.Addr
server *grpc.Server
cqueue chan net.Conn
errChan chan error
md metadata
logger logger.Logger
options listener.Options
}
func NewListener(opts ...listener.Option) listener.Listener {
options := listener.Options{}
for _, opt := range opts {
opt(&options)
}
return &grpcListener{
logger: options.Logger,
options: options,
}
}
func (l *grpcListener) Init(md md.Metadata) (err error) {
if err = l.parseMetadata(md); err != nil {
return
}
laddr, err := net.ResolveTCPAddr("tcp", l.options.Addr)
if err != nil {
return
}
ln, err := net.ListenTCP("tcp", laddr)
if err != nil {
return
}
var opts []grpc.ServerOption
if !l.md.insecure {
opts = append(opts, grpc.Creds(credentials.NewTLS(l.options.TLSConfig)))
}
l.server = grpc.NewServer(opts...)
l.addr = ln.Addr()
l.cqueue = make(chan net.Conn, l.md.backlog)
l.errChan = make(chan error, 1)
pb.RegisterGostTunelServer(l.server, &server{
cqueue: l.cqueue,
localAddr: l.addr,
logger: l.options.Logger,
})
go func() {
err := l.server.Serve(ln)
if err != nil {
l.errChan <- err
}
close(l.errChan)
}()
return
}
func (l *grpcListener) Accept() (conn net.Conn, err error) {
var ok bool
select {
case conn = <-l.cqueue:
case err, ok = <-l.errChan:
if !ok {
err = listener.ErrClosed
}
}
return
}
func (l *grpcListener) Close() error {
l.server.Stop()
return nil
}
func (l *grpcListener) Addr() net.Addr {
return l.addr
}

View File

@ -0,0 +1,29 @@
package grpc
import (
mdata "github.com/go-gost/gost/pkg/metadata"
)
const (
defaultBacklog = 128
)
type metadata struct {
backlog int
insecure bool
}
func (l *grpcListener) parseMetadata(md mdata.Metadata) (err error) {
const (
backlog = "backlog"
insecure = "grpcInsecure"
)
l.md.backlog = mdata.GetInt(md, backlog)
if l.md.backlog <= 0 {
l.md.backlog = defaultBacklog
}
l.md.insecure = mdata.GetBool(md, insecure)
return
}

120
pkg/listener/grpc/server.go Normal file
View File

@ -0,0 +1,120 @@
package grpc
import (
"errors"
"io"
"net"
"time"
pb "github.com/go-gost/gost/pkg/common/util/grpc/proto"
"github.com/go-gost/gost/pkg/logger"
)
type server struct {
cqueue chan net.Conn
localAddr net.Addr
pb.UnimplementedGostTunelServer
logger logger.Logger
}
func (s *server) Tunnel(srv pb.GostTunel_TunnelServer) error {
c := &conn{
s: srv,
localAddr: s.localAddr,
remoteAddr: &net.TCPAddr{},
closed: make(chan struct{}),
}
select {
case s.cqueue <- c:
default:
c.Close()
s.logger.Warnf("connection queue is full, client discarded")
}
<-c.closed
return nil
}
type conn struct {
s pb.GostTunel_TunnelServer
rb []byte
localAddr net.Addr
remoteAddr net.Addr
closed chan struct{}
}
func (c *conn) Read(b []byte) (n int, err error) {
select {
case <-c.s.Context().Done():
err = c.s.Context().Err()
return
case <-c.closed:
err = io.ErrClosedPipe
return
default:
}
if len(c.rb) == 0 {
chunk, err := c.s.Recv()
if err != nil {
return 0, err
}
c.rb = chunk.Data
}
n = copy(b, c.rb)
c.rb = c.rb[n:]
return
}
func (c *conn) Write(b []byte) (n int, err error) {
select {
case <-c.s.Context().Done():
err = c.s.Context().Err()
return
case <-c.closed:
err = io.ErrClosedPipe
return
default:
}
if err = c.s.Send(&pb.Chunk{
Data: b,
}); err != nil {
return
}
n = len(b)
return
}
func (c *conn) Close() error {
select {
case <-c.closed:
default:
close(c.closed)
}
return nil
}
func (c *conn) LocalAddr() net.Addr {
return c.localAddr
}
func (c *conn) RemoteAddr() net.Addr {
return c.remoteAddr
}
func (c *conn) SetDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "grpc", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}
func (c *conn) SetReadDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "grpc", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}
func (c *conn) SetWriteDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "grpc", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}

View File

@ -14,20 +14,20 @@ func init() {
}
type tcpListener struct {
addr string
md metadata
net.Listener
logger logger.Logger
logger logger.Logger
md metadata
options listener.Options
}
func NewListener(opts ...listener.Option) listener.Listener {
options := &listener.Options{}
options := listener.Options{}
for _, opt := range opts {
opt(options)
opt(&options)
}
return &tcpListener{
addr: options.Addr,
logger: options.Logger,
logger: options.Logger,
options: options,
}
}
@ -36,7 +36,7 @@ func (l *tcpListener) Init(md md.Metadata) (err error) {
return
}
laddr, err := net.ResolveTCPAddr("tcp", l.addr)
laddr, err := net.ResolveTCPAddr("tcp", l.options.Addr)
if err != nil {
return
}