mv non-core components to extended repo

This commit is contained in:
ginuerzh
2022-03-14 17:43:37 +08:00
parent bfc1f8472c
commit 5c5af49b0e
279 changed files with 608 additions and 14301 deletions

View File

@ -4,8 +4,8 @@ import (
"net"
"strconv"
"github.com/go-gost/gost/pkg/common/matcher"
"github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/gost/v3/pkg/common/matcher"
"github.com/go-gost/gost/v3/pkg/logger"
)
type Admission interface {

View File

@ -7,7 +7,7 @@ import (
"os"
"github.com/gin-gonic/gin"
"github.com/go-gost/gost/pkg/config"
"github.com/go-gost/gost/v3/pkg/config"
)
// swagger:parameters getConfigRequest

View File

@ -4,9 +4,9 @@ import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/go-gost/gost/pkg/config"
"github.com/go-gost/gost/pkg/config/parsing"
"github.com/go-gost/gost/pkg/registry"
"github.com/go-gost/gost/v3/pkg/config"
"github.com/go-gost/gost/v3/pkg/config/parsing"
"github.com/go-gost/gost/v3/pkg/registry"
)
// swagger:parameters createAdmissionRequest

View File

@ -4,9 +4,9 @@ import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/go-gost/gost/pkg/config"
"github.com/go-gost/gost/pkg/config/parsing"
"github.com/go-gost/gost/pkg/registry"
"github.com/go-gost/gost/v3/pkg/config"
"github.com/go-gost/gost/v3/pkg/config/parsing"
"github.com/go-gost/gost/v3/pkg/registry"
)
// swagger:parameters createAutherRequest

View File

@ -4,9 +4,9 @@ import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/go-gost/gost/pkg/config"
"github.com/go-gost/gost/pkg/config/parsing"
"github.com/go-gost/gost/pkg/registry"
"github.com/go-gost/gost/v3/pkg/config"
"github.com/go-gost/gost/v3/pkg/config/parsing"
"github.com/go-gost/gost/v3/pkg/registry"
)
// swagger:parameters createBypassRequest

View File

@ -4,9 +4,9 @@ import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/go-gost/gost/pkg/config"
"github.com/go-gost/gost/pkg/config/parsing"
"github.com/go-gost/gost/pkg/registry"
"github.com/go-gost/gost/v3/pkg/config"
"github.com/go-gost/gost/v3/pkg/config/parsing"
"github.com/go-gost/gost/v3/pkg/registry"
)
// swagger:parameters createChainRequest

View File

@ -4,9 +4,9 @@ import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/go-gost/gost/pkg/config"
"github.com/go-gost/gost/pkg/config/parsing"
"github.com/go-gost/gost/pkg/registry"
"github.com/go-gost/gost/v3/pkg/config"
"github.com/go-gost/gost/v3/pkg/config/parsing"
"github.com/go-gost/gost/v3/pkg/registry"
)
// swagger:parameters createHostsRequest

View File

@ -4,9 +4,9 @@ import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/go-gost/gost/pkg/config"
"github.com/go-gost/gost/pkg/config/parsing"
"github.com/go-gost/gost/pkg/registry"
"github.com/go-gost/gost/v3/pkg/config"
"github.com/go-gost/gost/v3/pkg/config/parsing"
"github.com/go-gost/gost/v3/pkg/registry"
)
// swagger:parameters createResolverRequest

View File

@ -4,9 +4,9 @@ import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/go-gost/gost/pkg/config"
"github.com/go-gost/gost/pkg/config/parsing"
"github.com/go-gost/gost/pkg/registry"
"github.com/go-gost/gost/v3/pkg/config"
"github.com/go-gost/gost/v3/pkg/config/parsing"
"github.com/go-gost/gost/v3/pkg/registry"
)
// swagger:parameters createServiceRequest

View File

@ -5,8 +5,8 @@ import (
"time"
"github.com/gin-gonic/gin"
"github.com/go-gost/gost/pkg/auth"
"github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/gost/v3/pkg/auth"
"github.com/go-gost/gost/v3/pkg/logger"
)
func mwLogger() gin.HandlerFunc {

View File

@ -6,8 +6,8 @@ import (
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/go-gost/gost/pkg/auth"
"github.com/go-gost/gost/pkg/service"
"github.com/go-gost/gost/v3/pkg/auth"
"github.com/go-gost/gost/v3/pkg/service"
)
type options struct {

View File

@ -19,7 +19,7 @@ definitions:
type: string
x-go-name: PathPrefix
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
AdmissionConfig:
properties:
matchers:
@ -38,7 +38,7 @@ definitions:
type: string
x-go-name: Type
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
AuthConfig:
properties:
password:
@ -48,7 +48,7 @@ definitions:
type: string
x-go-name: Username
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
AutherConfig:
properties:
auths:
@ -64,7 +64,7 @@ definitions:
type: string
x-go-name: Type
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
BypassConfig:
properties:
matchers:
@ -83,7 +83,7 @@ definitions:
type: string
x-go-name: Type
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
ChainConfig:
properties:
hops:
@ -97,7 +97,7 @@ definitions:
selector:
$ref: '#/definitions/SelectorConfig'
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
Config:
properties:
admissions:
@ -146,7 +146,7 @@ definitions:
tls:
$ref: '#/definitions/TLSConfig'
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
ConnectorConfig:
properties:
auth:
@ -162,7 +162,7 @@ definitions:
type: string
x-go-name: Type
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
DialerConfig:
properties:
auth:
@ -178,7 +178,7 @@ definitions:
type: string
x-go-name: Type
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
Duration:
description: |-
A Duration represents the elapsed time between two instants
@ -197,7 +197,7 @@ definitions:
type: array
x-go-name: Targets
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
HandlerConfig:
properties:
auth:
@ -223,7 +223,7 @@ definitions:
type: string
x-go-name: Type
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
HopConfig:
properties:
bypass:
@ -246,7 +246,7 @@ definitions:
selector:
$ref: '#/definitions/SelectorConfig'
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
HostMappingConfig:
properties:
aliases:
@ -261,7 +261,7 @@ definitions:
type: string
x-go-name: IP
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
HostsConfig:
properties:
mappings:
@ -277,7 +277,7 @@ definitions:
type: string
x-go-name: Type
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
ListenerConfig:
properties:
auth:
@ -299,7 +299,7 @@ definitions:
type: string
x-go-name: Type
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
LogConfig:
properties:
format:
@ -312,7 +312,7 @@ definitions:
type: string
x-go-name: Output
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
MetricsConfig:
properties:
addr:
@ -325,7 +325,7 @@ definitions:
type: string
x-go-name: Path
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
NameserverConfig:
properties:
addr:
@ -348,7 +348,7 @@ definitions:
ttl:
$ref: '#/definitions/Duration'
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
NodeConfig:
properties:
addr:
@ -371,7 +371,7 @@ definitions:
type: string
x-go-name: Resolver
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
ProfilingConfig:
properties:
addr:
@ -381,7 +381,7 @@ definitions:
type: boolean
x-go-name: Enable
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
ResolverConfig:
properties:
name:
@ -397,7 +397,7 @@ definitions:
type: string
x-go-name: Type
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
Response:
properties:
code:
@ -408,7 +408,7 @@ definitions:
type: string
x-go-name: Msg
type: object
x-go-package: github.com/go-gost/gost/pkg/api
x-go-package: github.com/go-gost/gost/v3/pkg/api
SelectorConfig:
properties:
failTimeout:
@ -421,7 +421,7 @@ definitions:
type: string
x-go-name: Strategy
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
ServiceConfig:
properties:
addr:
@ -449,7 +449,7 @@ definitions:
type: string
x-go-name: Resolver
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
TLSConfig:
properties:
caFile:
@ -468,7 +468,7 @@ definitions:
type: string
x-go-name: ServerName
type: object
x-go-package: github.com/go-gost/gost/pkg/config
x-go-package: github.com/go-gost/gost/v3/pkg/config
info:
title: Documentation of Web API.
version: 1.0.0

View File

@ -5,20 +5,20 @@ type Authenticator interface {
Authenticate(user, password string) bool
}
// LocalAuthenticator is an Authenticator that authenticates client by local key-value pairs.
type MapAuthenticator struct {
// authenticator is an Authenticator that authenticates client by key-value pairs.
type authenticator struct {
kvs map[string]string
}
// NewMapAuthenticator creates an Authenticator that authenticates client by local infos.
func NewMapAuthenticator(kvs map[string]string) Authenticator {
return &MapAuthenticator{
// NewAuthenticator creates an Authenticator that authenticates client by pre-defined user mapping.
func NewAuthenticator(kvs map[string]string) Authenticator {
return &authenticator{
kvs: kvs,
}
}
// Authenticate checks the validity of the provided user-password pair.
func (au *MapAuthenticator) Authenticate(user, password string) bool {
func (au *authenticator) Authenticate(user, password string) bool {
if au == nil || len(au.kvs) == 0 {
return true
}

View File

@ -4,8 +4,8 @@ import (
"net"
"strconv"
"github.com/go-gost/gost/pkg/common/matcher"
"github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/gost/v3/pkg/common/matcher"
"github.com/go-gost/gost/v3/pkg/logger"
)
// Bypass is a filter of address (IP or domain).

View File

@ -4,9 +4,9 @@ import (
"sync/atomic"
"time"
"github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/hosts"
"github.com/go-gost/gost/pkg/resolver"
"github.com/go-gost/gost/v3/pkg/bypass"
"github.com/go-gost/gost/v3/pkg/hosts"
"github.com/go-gost/gost/v3/pkg/resolver"
)
type Node struct {

View File

@ -5,9 +5,9 @@ import (
"fmt"
"net"
"github.com/go-gost/gost/pkg/hosts"
"github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/gost/pkg/resolver"
"github.com/go-gost/gost/v3/pkg/hosts"
"github.com/go-gost/gost/v3/pkg/logger"
"github.com/go-gost/gost/v3/pkg/resolver"
)
func resolve(ctx context.Context, network, addr string, r resolver.Resolver, hosts hosts.HostMapper, log logger.Logger) (string, error) {

View File

@ -7,10 +7,10 @@ import (
"net"
"time"
"github.com/go-gost/gost/pkg/common/net/dialer"
"github.com/go-gost/gost/pkg/common/util/udp"
"github.com/go-gost/gost/pkg/connector"
"github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/gost/v3/pkg/common/net/dialer"
"github.com/go-gost/gost/v3/pkg/connector"
"github.com/go-gost/gost/v3/pkg/internal/util/udp"
"github.com/go-gost/gost/v3/pkg/logger"
)
var (

View File

@ -7,10 +7,10 @@ import (
"net"
"time"
"github.com/go-gost/gost/pkg/connector"
"github.com/go-gost/gost/pkg/hosts"
"github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/gost/pkg/resolver"
"github.com/go-gost/gost/v3/pkg/connector"
"github.com/go-gost/gost/v3/pkg/hosts"
"github.com/go-gost/gost/v3/pkg/logger"
"github.com/go-gost/gost/v3/pkg/resolver"
)
type Router struct {

View File

@ -5,9 +5,9 @@ import (
"net"
"time"
net_dialer "github.com/go-gost/gost/pkg/common/net/dialer"
"github.com/go-gost/gost/pkg/connector"
"github.com/go-gost/gost/pkg/dialer"
net_dialer "github.com/go-gost/gost/v3/pkg/common/net/dialer"
"github.com/go-gost/gost/v3/pkg/connector"
"github.com/go-gost/gost/v3/pkg/dialer"
)
type Transport struct {

View File

@ -6,7 +6,7 @@ import (
"net"
"syscall"
"github.com/go-gost/gost/pkg/admission"
"github.com/go-gost/gost/v3/pkg/admission"
)
var (

View File

@ -3,7 +3,7 @@ package admission
import (
"net"
"github.com/go-gost/gost/pkg/admission"
"github.com/go-gost/gost/v3/pkg/admission"
)
type listener struct {

View File

@ -6,7 +6,7 @@ import (
"net"
"syscall"
"github.com/go-gost/gost/pkg/metrics"
"github.com/go-gost/gost/v3/pkg/metrics"
)
var (

View File

@ -7,7 +7,7 @@ import (
"syscall"
"time"
"github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/gost/v3/pkg/logger"
)
var (

View File

@ -3,9 +3,9 @@ package relay
import (
"net"
"github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/common/bufpool"
"github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/gost/v3/pkg/bypass"
"github.com/go-gost/gost/v3/pkg/common/bufpool"
"github.com/go-gost/gost/v3/pkg/logger"
)
type UDPRelay struct {

View File

@ -5,7 +5,7 @@ import (
"io"
"net"
"github.com/go-gost/gost/pkg/common/bufpool"
"github.com/go-gost/gost/v3/pkg/common/bufpool"
)
func Transport(rw1, rw2 io.ReadWriter) error {

View File

@ -1,148 +0,0 @@
// 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 = []any{
(*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 any, i int) any {
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

@ -1,10 +0,0 @@
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

@ -1,133 +0,0 @@
// 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 any, 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

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

View File

@ -1,115 +0,0 @@
package kcp
import (
"crypto/sha1"
"github.com/xtaci/kcp-go/v5"
"golang.org/x/crypto/pbkdf2"
)
var (
// DefaultSalt is the default salt for KCP cipher.
DefaultSalt = "kcp-go"
)
var (
// DefaultKCPConfig is the default KCP config.
DefaultConfig = &Config{
Key: "it's a secrect",
Crypt: "aes",
Mode: "fast",
MTU: 1350,
SndWnd: 1024,
RcvWnd: 1024,
DataShard: 10,
ParityShard: 3,
DSCP: 0,
NoComp: false,
AckNodelay: false,
NoDelay: 0,
Interval: 50,
Resend: 0,
NoCongestion: 0,
SockBuf: 4194304,
KeepAlive: 10,
SnmpLog: "",
SnmpPeriod: 60,
Signal: false,
TCP: false,
}
)
// KCPConfig describes the config for KCP.
type Config struct {
Key string `json:"key"`
Crypt string `json:"crypt"`
Mode string `json:"mode"`
MTU int `json:"mtu"`
SndWnd int `json:"sndwnd"`
RcvWnd int `json:"rcvwnd"`
DataShard int `json:"datashard"`
ParityShard int `json:"parityshard"`
DSCP int `json:"dscp"`
NoComp bool `json:"nocomp"`
AckNodelay bool `json:"acknodelay"`
NoDelay int `json:"nodelay"`
Interval int `json:"interval"`
Resend int `json:"resend"`
NoCongestion int `json:"nc"`
SockBuf int `json:"sockbuf"`
KeepAlive int `json:"keepalive"`
SnmpLog string `json:"snmplog"`
SnmpPeriod int `json:"snmpperiod"`
Signal bool `json:"signal"` // Signal enables the signal SIGUSR1 feature.
TCP bool `json:"tcp"`
}
// Init initializes the KCP config.
func (c *Config) Init() {
switch c.Mode {
case "normal":
c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 0, 40, 2, 1
case "fast":
c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 0, 30, 2, 1
case "fast2":
c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 20, 2, 1
case "fast3":
c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 10, 2, 1
}
}
func BlockCrypt(key, crypt, salt string) (block kcp.BlockCrypt) {
pass := pbkdf2.Key([]byte(key), []byte(salt), 4096, 32, sha1.New)
switch crypt {
case "sm4":
block, _ = kcp.NewSM4BlockCrypt(pass[:16])
case "tea":
block, _ = kcp.NewTEABlockCrypt(pass[:16])
case "xor":
block, _ = kcp.NewSimpleXORBlockCrypt(pass)
case "none":
block, _ = kcp.NewNoneBlockCrypt(pass)
case "aes-128":
block, _ = kcp.NewAESBlockCrypt(pass[:16])
case "aes-192":
block, _ = kcp.NewAESBlockCrypt(pass[:24])
case "blowfish":
block, _ = kcp.NewBlowfishBlockCrypt(pass)
case "twofish":
block, _ = kcp.NewTwofishBlockCrypt(pass)
case "cast5":
block, _ = kcp.NewCast5BlockCrypt(pass[:16])
case "3des":
block, _ = kcp.NewTripleDESBlockCrypt(pass[:24])
case "xtea":
block, _ = kcp.NewXTEABlockCrypt(pass[:16])
case "salsa20":
block, _ = kcp.NewSalsa20BlockCrypt(pass)
case "aes":
fallthrough
default: // aes
block, _ = kcp.NewAESBlockCrypt(pass)
}
return
}

View File

@ -1,34 +0,0 @@
package kcp
import (
"net"
"github.com/golang/snappy"
)
type kcpCompStreamConn struct {
net.Conn
w *snappy.Writer
r *snappy.Reader
}
func CompStreamConn(conn net.Conn) net.Conn {
return &kcpCompStreamConn{
Conn: conn,
w: snappy.NewBufferedWriter(conn),
r: snappy.NewReader(conn),
}
}
func (c *kcpCompStreamConn) Read(b []byte) (n int, err error) {
return c.r.Read(b)
}
func (c *kcpCompStreamConn) Write(b []byte) (n int, err error) {
n, err = c.w.Write(b)
if err != nil {
return
}
err = c.w.Flush()
return n, err
}

View File

@ -1,96 +0,0 @@
package ss
import (
"bytes"
"net"
"github.com/go-gost/gosocks5"
"github.com/go-gost/gost/pkg/common/bufpool"
)
var (
DefaultBufferSize = 4096
)
var (
_ net.PacketConn = (*UDPConn)(nil)
_ net.Conn = (*UDPConn)(nil)
)
type UDPConn struct {
net.PacketConn
raddr net.Addr
taddr net.Addr
bufferSize int
}
func UDPClientConn(c net.PacketConn, remoteAddr, targetAddr net.Addr, bufferSize int) *UDPConn {
return &UDPConn{
PacketConn: c,
raddr: remoteAddr,
taddr: targetAddr,
bufferSize: bufferSize,
}
}
func UDPServerConn(c net.PacketConn, remoteAddr net.Addr, bufferSize int) *UDPConn {
return &UDPConn{
PacketConn: c,
raddr: remoteAddr,
bufferSize: bufferSize,
}
}
func (c *UDPConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
rbuf := bufpool.Get(c.bufferSize)
defer bufpool.Put(rbuf)
n, _, err = c.PacketConn.ReadFrom(*rbuf)
if err != nil {
return
}
saddr := gosocks5.Addr{}
addrLen, err := saddr.ReadFrom(bytes.NewReader((*rbuf)[:n]))
if err != nil {
return
}
n = copy(b, (*rbuf)[addrLen:n])
addr, err = net.ResolveUDPAddr("udp", saddr.String())
return
}
func (c *UDPConn) Read(b []byte) (n int, err error) {
n, _, err = c.ReadFrom(b)
return
}
func (c *UDPConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
wbuf := bufpool.Get(c.bufferSize)
defer bufpool.Put(wbuf)
socksAddr := gosocks5.Addr{}
if err = socksAddr.ParseFrom(addr.String()); err != nil {
return
}
addrLen, err := socksAddr.Encode(*wbuf)
if err != nil {
return
}
n = copy((*wbuf)[addrLen:], b)
_, err = c.PacketConn.WriteTo((*wbuf)[:addrLen+n], c.raddr)
return
}
func (c *UDPConn) Write(b []byte) (n int, err error) {
return c.WriteTo(b, c.taddr)
}
func (c *UDPConn) RemoteAddr() net.Addr {
return c.raddr
}

View File

@ -1,60 +0,0 @@
package ss
import (
"bytes"
"net"
"github.com/shadowsocks/go-shadowsocks2/core"
ss "github.com/shadowsocks/shadowsocks-go/shadowsocks"
)
type shadowCipher struct {
cipher *ss.Cipher
}
func (c *shadowCipher) StreamConn(conn net.Conn) net.Conn {
return ss.NewConn(conn, c.cipher.Copy())
}
func (c *shadowCipher) PacketConn(conn net.PacketConn) net.PacketConn {
return ss.NewSecurePacketConn(conn, c.cipher.Copy())
}
func ShadowCipher(method, password string, key string) (core.Cipher, error) {
if method == "" && password == "" {
return nil, nil
}
c, _ := ss.NewCipher(method, password)
if c != nil {
return &shadowCipher{cipher: c}, nil
}
return core.PickCipher(method, []byte(key), password)
}
// Due to in/out byte length is inconsistent of the shadowsocks.Conn.Write,
// we wrap around it to make io.Copy happy.
type shadowConn struct {
net.Conn
wbuf *bytes.Buffer
}
func ShadowConn(conn net.Conn, header []byte) net.Conn {
return &shadowConn{
Conn: conn,
wbuf: bytes.NewBuffer(header),
}
}
func (c *shadowConn) Write(b []byte) (n int, err error) {
n = len(b) // force byte length consistent
if c.wbuf.Len() > 0 {
c.wbuf.Write(b) // append the data to the cached header
_, err = c.Conn.Write(c.wbuf.Bytes())
c.wbuf.Reset()
return
}
_, err = c.Conn.Write(b)
return
}

View File

@ -62,8 +62,9 @@ type APIConfig struct {
}
type MetricsConfig struct {
Addr string `json:"addr"`
Path string `json:"path"`
Enable bool `json:"enable"`
Addr string `json:"addr"`
Path string `json:"path"`
}
type TLSConfig struct {

View File

@ -1,14 +1,14 @@
package parsing
import (
"github.com/go-gost/gost/pkg/chain"
tls_util "github.com/go-gost/gost/pkg/common/util/tls"
"github.com/go-gost/gost/pkg/config"
"github.com/go-gost/gost/pkg/connector"
"github.com/go-gost/gost/pkg/dialer"
"github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
"github.com/go-gost/gost/v3/pkg/chain"
tls_util "github.com/go-gost/gost/v3/pkg/common/util/tls"
"github.com/go-gost/gost/v3/pkg/config"
"github.com/go-gost/gost/v3/pkg/connector"
"github.com/go-gost/gost/v3/pkg/dialer"
"github.com/go-gost/gost/v3/pkg/logger"
"github.com/go-gost/gost/v3/pkg/metadata"
"github.com/go-gost/gost/v3/pkg/registry"
)
func ParseChain(cfg *config.ChainConfig) (chain.Chainer, error) {

View File

@ -4,16 +4,16 @@ import (
"net"
"net/url"
"github.com/go-gost/gost/pkg/admission"
"github.com/go-gost/gost/pkg/auth"
"github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/config"
hostspkg "github.com/go-gost/gost/pkg/hosts"
"github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/gost/pkg/registry"
"github.com/go-gost/gost/pkg/resolver"
resolver_impl "github.com/go-gost/gost/pkg/resolver/impl"
"github.com/go-gost/gost/v3/pkg/admission"
"github.com/go-gost/gost/v3/pkg/auth"
"github.com/go-gost/gost/v3/pkg/bypass"
"github.com/go-gost/gost/v3/pkg/chain"
"github.com/go-gost/gost/v3/pkg/config"
hostspkg "github.com/go-gost/gost/v3/pkg/hosts"
"github.com/go-gost/gost/v3/pkg/logger"
"github.com/go-gost/gost/v3/pkg/registry"
"github.com/go-gost/gost/v3/pkg/resolver"
resolver_impl "github.com/go-gost/gost/v3/pkg/resolver/impl"
)
func ParseAuther(cfg *config.AutherConfig) auth.Authenticator {
@ -33,14 +33,14 @@ func ParseAuther(cfg *config.AutherConfig) auth.Authenticator {
if len(m) == 0 {
return nil
}
return auth.NewMapAuthenticator(m)
return auth.NewAuthenticator(m)
}
func ParseAutherFromAuth(au *config.AuthConfig) auth.Authenticator {
if au == nil || au.Username == "" {
return nil
}
return auth.NewMapAuthenticator(map[string]string{
return auth.NewAuthenticator(map[string]string{
au.Username: au.Password,
})
}

View File

@ -3,15 +3,15 @@ package parsing
import (
"strings"
"github.com/go-gost/gost/pkg/chain"
tls_util "github.com/go-gost/gost/pkg/common/util/tls"
"github.com/go-gost/gost/pkg/config"
"github.com/go-gost/gost/pkg/handler"
"github.com/go-gost/gost/pkg/listener"
"github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
"github.com/go-gost/gost/pkg/service"
"github.com/go-gost/gost/v3/pkg/chain"
tls_util "github.com/go-gost/gost/v3/pkg/common/util/tls"
"github.com/go-gost/gost/v3/pkg/config"
"github.com/go-gost/gost/v3/pkg/handler"
"github.com/go-gost/gost/v3/pkg/listener"
"github.com/go-gost/gost/v3/pkg/logger"
"github.com/go-gost/gost/v3/pkg/metadata"
"github.com/go-gost/gost/v3/pkg/registry"
"github.com/go-gost/gost/v3/pkg/service"
)
func ParseService(cfg *config.ServiceConfig) (service.Service, error) {

View File

@ -10,36 +10,6 @@ var (
ErrBindUnsupported = errors.New("bind unsupported")
)
type Accepter interface {
Accept() (net.Conn, error)
Addr() net.Addr
Close() error
}
type Binder interface {
Bind(ctx context.Context, conn net.Conn, network, address string, opts ...BindOption) (net.Listener, error)
}
type AcceptError struct {
err error
}
func NewAcceptError(err error) error {
return &AcceptError{err: err}
}
func (e *AcceptError) Error() string {
return e.err.Error()
}
func (e *AcceptError) Timeout() bool {
return false
}
func (e *AcceptError) Temporary() bool {
return true
}
func (e *AcceptError) Unwrap() error {
return e.err
}

View File

@ -4,7 +4,7 @@ import (
"context"
"net"
"github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/v3/pkg/metadata"
)
// Connector is responsible for connecting to the destination address.

View File

@ -4,9 +4,9 @@ import (
"context"
"net"
"github.com/go-gost/gost/pkg/connector"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
"github.com/go-gost/gost/v3/pkg/connector"
md "github.com/go-gost/gost/v3/pkg/metadata"
"github.com/go-gost/gost/v3/pkg/registry"
)
func init() {

View File

@ -11,11 +11,11 @@ import (
"net/url"
"time"
"github.com/go-gost/gost/pkg/common/util/socks"
"github.com/go-gost/gost/pkg/connector"
"github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
"github.com/go-gost/gost/v3/pkg/connector"
"github.com/go-gost/gost/v3/pkg/internal/util/socks"
"github.com/go-gost/gost/v3/pkg/logger"
md "github.com/go-gost/gost/v3/pkg/metadata"
"github.com/go-gost/gost/v3/pkg/registry"
)
func init() {

View File

@ -4,7 +4,7 @@ import (
"net/http"
"time"
mdata "github.com/go-gost/gost/pkg/metadata"
mdata "github.com/go-gost/gost/v3/pkg/metadata"
)
type metadata struct {

View File

@ -12,11 +12,11 @@ import (
"net/url"
"time"
"github.com/go-gost/gost/pkg/connector"
http2_util "github.com/go-gost/gost/pkg/internal/util/http2"
"github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
"github.com/go-gost/gost/v3/pkg/connector"
http2_util "github.com/go-gost/gost/v3/pkg/internal/util/http2"
"github.com/go-gost/gost/v3/pkg/logger"
md "github.com/go-gost/gost/v3/pkg/metadata"
"github.com/go-gost/gost/v3/pkg/registry"
)
func init() {

View File

@ -3,7 +3,7 @@ package http2
import (
"time"
mdata "github.com/go-gost/gost/pkg/metadata"
mdata "github.com/go-gost/gost/v3/pkg/metadata"
)
const (

View File

@ -5,7 +5,7 @@ import (
"net/url"
"time"
"github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/gost/v3/pkg/logger"
)
type Options struct {

View File

@ -1,133 +0,0 @@
package relay
import (
"context"
"fmt"
"net"
"strconv"
"github.com/go-gost/gost/pkg/common/util/mux"
"github.com/go-gost/gost/pkg/common/util/socks"
"github.com/go-gost/gost/pkg/common/util/udp"
"github.com/go-gost/gost/pkg/connector"
"github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/relay"
)
// Bind implements connector.Binder.
func (c *relayConnector) Bind(ctx context.Context, conn net.Conn, network, address string, opts ...connector.BindOption) (net.Listener, error) {
log := c.options.Logger.WithFields(map[string]any{
"network": network,
"address": address,
})
log.Infof("bind on %s/%s", address, network)
options := connector.BindOptions{}
for _, opt := range opts {
opt(&options)
}
switch network {
case "tcp", "tcp4", "tcp6":
return c.bindTCP(ctx, conn, network, address, log)
case "udp", "udp4", "udp6":
return c.bindUDP(ctx, conn, network, address, &options, log)
default:
err := fmt.Errorf("network %s is unsupported", network)
log.Error(err)
return nil, err
}
}
func (c *relayConnector) bindTCP(ctx context.Context, conn net.Conn, network, address string, log logger.Logger) (net.Listener, error) {
laddr, err := c.bind(conn, relay.BIND, network, address)
if err != nil {
return nil, err
}
log.Debugf("bind on %s/%s OK", laddr, laddr.Network())
session, err := mux.ServerSession(conn)
if err != nil {
return nil, err
}
return &tcpListener{
addr: laddr,
session: session,
logger: log,
}, nil
}
func (c *relayConnector) bindUDP(ctx context.Context, conn net.Conn, network, address string, opts *connector.BindOptions, log logger.Logger) (net.Listener, error) {
laddr, err := c.bind(conn, relay.FUDP|relay.BIND, network, address)
if err != nil {
return nil, err
}
log.Debugf("bind on %s/%s OK", laddr, laddr.Network())
ln := udp.NewListener(
socks.UDPTunClientPacketConn(conn),
laddr,
opts.Backlog,
opts.UDPDataQueueSize, opts.UDPDataBufferSize,
opts.UDPConnTTL,
log)
return ln, nil
}
func (c *relayConnector) bind(conn net.Conn, cmd uint8, network, address string) (net.Addr, error) {
req := relay.Request{
Version: relay.Version1,
Flags: cmd,
}
if c.options.Auth != nil {
pwd, _ := c.options.Auth.Password()
req.Features = append(req.Features, &relay.UserAuthFeature{
Username: c.options.Auth.Username(),
Password: pwd,
})
}
fa := &relay.AddrFeature{}
fa.ParseFrom(address)
req.Features = append(req.Features, fa)
if _, err := req.WriteTo(conn); err != nil {
return nil, err
}
// first reply, bind status
resp := relay.Response{}
if _, err := resp.ReadFrom(conn); err != nil {
return nil, err
}
if resp.Status != relay.StatusOK {
return nil, fmt.Errorf("bind on %s/%s failed", address, network)
}
var addr string
for _, f := range resp.Features {
if f.Type() == relay.FeatureAddr {
if fa, ok := f.(*relay.AddrFeature); ok {
addr = net.JoinHostPort(fa.Host, strconv.Itoa(int(fa.Port)))
}
}
}
var baddr net.Addr
var err error
switch network {
case "tcp", "tcp4", "tcp6":
baddr, err = net.ResolveTCPAddr(network, addr)
case "udp", "udp4", "udp6":
baddr, err = net.ResolveUDPAddr(network, addr)
default:
err = fmt.Errorf("unknown network %s", network)
}
if err != nil {
return nil, err
}
return baddr, nil
}

View File

@ -1,132 +0,0 @@
package relay
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"io"
"math"
"net"
"sync"
"github.com/go-gost/relay"
)
type tcpConn struct {
net.Conn
wbuf bytes.Buffer
once sync.Once
}
func (c *tcpConn) Read(b []byte) (n int, err error) {
c.once.Do(func() {
err = readResponse(c.Conn)
})
if err != nil {
return
}
return c.Conn.Read(b)
}
func (c *tcpConn) Write(b []byte) (n int, err error) {
n = len(b) // force byte length consistent
if c.wbuf.Len() > 0 {
c.wbuf.Write(b) // append the data to the cached header
_, err = c.Conn.Write(c.wbuf.Bytes())
c.wbuf.Reset()
return
}
_, err = c.Conn.Write(b)
return
}
type udpConn struct {
net.Conn
wbuf bytes.Buffer
once sync.Once
}
func (c *udpConn) Read(b []byte) (n int, err error) {
c.once.Do(func() {
err = readResponse(c.Conn)
})
if err != nil {
return
}
var bb [2]byte
_, err = io.ReadFull(c.Conn, bb[:])
if err != nil {
return
}
dlen := int(binary.BigEndian.Uint16(bb[:]))
if len(b) >= dlen {
return io.ReadFull(c.Conn, b[:dlen])
}
buf := make([]byte, dlen)
_, err = io.ReadFull(c.Conn, buf)
n = copy(b, buf)
return
}
func (c *udpConn) Write(b []byte) (n int, err error) {
if len(b) > math.MaxUint16 {
err = errors.New("write: data maximum exceeded")
return
}
n = len(b)
if c.wbuf.Len() > 0 {
var bb [2]byte
binary.BigEndian.PutUint16(bb[:], uint16(len(b)))
c.wbuf.Write(bb[:])
c.wbuf.Write(b) // append the data to the cached header
_, err = c.wbuf.WriteTo(c.Conn)
return
}
var bb [2]byte
binary.BigEndian.PutUint16(bb[:], uint16(len(b)))
_, err = c.Conn.Write(bb[:])
if err != nil {
return
}
return c.Conn.Write(b)
}
func readResponse(r io.Reader) (err error) {
resp := relay.Response{}
_, err = resp.ReadFrom(r)
if err != nil {
return
}
if resp.Version != relay.Version1 {
err = relay.ErrBadVersion
return
}
if resp.Status != relay.StatusOK {
err = fmt.Errorf("status %d", resp.Status)
return
}
return nil
}
type bindConn struct {
net.Conn
localAddr net.Addr
remoteAddr net.Addr
}
func (c *bindConn) LocalAddr() net.Addr {
return c.localAddr
}
func (c *bindConn) RemoteAddr() net.Addr {
return c.remoteAddr
}

View File

@ -1,127 +0,0 @@
package relay
import (
"context"
"fmt"
"net"
"time"
"github.com/go-gost/gost/pkg/common/util/socks"
"github.com/go-gost/gost/pkg/connector"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
"github.com/go-gost/relay"
)
func init() {
registry.ConnectorRegistry().Register("relay", NewConnector)
}
type relayConnector struct {
md metadata
options connector.Options
}
func NewConnector(opts ...connector.Option) connector.Connector {
options := connector.Options{}
for _, opt := range opts {
opt(&options)
}
return &relayConnector{
options: options,
}
}
func (c *relayConnector) Init(md md.Metadata) (err error) {
return c.parseMetadata(md)
}
func (c *relayConnector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
log := c.options.Logger.WithFields(map[string]any{
"remote": conn.RemoteAddr().String(),
"local": conn.LocalAddr().String(),
"network": network,
"address": address,
})
log.Infof("connect %s/%s", address, network)
if c.md.connectTimeout > 0 {
conn.SetDeadline(time.Now().Add(c.md.connectTimeout))
defer conn.SetDeadline(time.Time{})
}
req := relay.Request{
Version: relay.Version1,
Flags: relay.CONNECT,
}
if network == "udp" || network == "udp4" || network == "udp6" {
req.Flags |= relay.FUDP
// UDP association
if address == "" {
baddr, err := c.bind(conn, relay.FUDP|relay.BIND, network, address)
if err != nil {
return nil, err
}
log.Debugf("associate on %s OK", baddr)
return socks.UDPTunClientConn(conn, nil), nil
}
}
if c.options.Auth != nil {
pwd, _ := c.options.Auth.Password()
req.Features = append(req.Features, &relay.UserAuthFeature{
Username: c.options.Auth.Username(),
Password: pwd,
})
}
if address != "" {
af := &relay.AddrFeature{}
if err := af.ParseFrom(address); err != nil {
return nil, err
}
// forward mode if port is 0.
if af.Port > 0 {
req.Features = append(req.Features, af)
}
}
if c.md.noDelay {
if _, err := req.WriteTo(conn); err != nil {
return nil, err
}
}
switch network {
case "tcp", "tcp4", "tcp6":
cc := &tcpConn{
Conn: conn,
}
if !c.md.noDelay {
if _, err := req.WriteTo(&cc.wbuf); err != nil {
return nil, err
}
}
conn = cc
case "udp", "udp4", "udp6":
cc := &udpConn{
Conn: conn,
}
if !c.md.noDelay {
if _, err := req.WriteTo(&cc.wbuf); err != nil {
return nil, err
}
}
conn = cc
default:
err := fmt.Errorf("network %s is unsupported", network)
log.Error(err)
return nil, err
}
return conn, nil
}

View File

@ -1,73 +0,0 @@
package relay
import (
"fmt"
"net"
"strconv"
"github.com/go-gost/gost/pkg/common/util/mux"
"github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/relay"
)
type tcpListener struct {
addr net.Addr
session *mux.Session
logger logger.Logger
}
func (p *tcpListener) Accept() (net.Conn, error) {
cc, err := p.session.Accept()
if err != nil {
return nil, err
}
conn, err := p.getPeerConn(cc)
if err != nil {
cc.Close()
return nil, err
}
return conn, nil
}
func (p *tcpListener) getPeerConn(conn net.Conn) (net.Conn, error) {
// second reply, peer connected
resp := relay.Response{}
if _, err := resp.ReadFrom(conn); err != nil {
return nil, err
}
if resp.Status != relay.StatusOK {
err := fmt.Errorf("peer connect failed")
return nil, err
}
var address string
for _, f := range resp.Features {
if f.Type() == relay.FeatureAddr {
if fa, ok := f.(*relay.AddrFeature); ok {
address = net.JoinHostPort(fa.Host, strconv.Itoa(int(fa.Port)))
}
}
}
raddr, err := net.ResolveTCPAddr("tcp", address)
if err != nil {
return nil, err
}
return &bindConn{
Conn: conn,
localAddr: p.addr,
remoteAddr: raddr,
}, nil
}
func (p *tcpListener) Addr() net.Addr {
return p.addr
}
func (p *tcpListener) Close() error {
return p.session.Close()
}

View File

@ -1,24 +0,0 @@
package relay
import (
"time"
mdata "github.com/go-gost/gost/pkg/metadata"
)
type metadata struct {
connectTimeout time.Duration
noDelay bool
}
func (c *relayConnector) parseMetadata(md mdata.Metadata) (err error) {
const (
connectTimeout = "connectTimeout"
noDelay = "nodelay"
)
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
c.md.noDelay = mdata.GetBool(md, noDelay)
return
}

View File

@ -1,128 +0,0 @@
package sni
import (
"bufio"
"bytes"
"encoding/base64"
"encoding/binary"
"hash/crc32"
"io"
"net"
"strings"
dissector "github.com/go-gost/tls-dissector"
)
type sniClientConn struct {
host string
obfuscated bool
net.Conn
}
func (c *sniClientConn) Write(p []byte) (int, error) {
b, err := c.obfuscate(p)
if err != nil {
return 0, err
}
if _, err = c.Conn.Write(b); err != nil {
return 0, err
}
return len(p), nil
}
func (c *sniClientConn) obfuscate(p []byte) ([]byte, error) {
if c.host == "" {
return p, nil
}
if c.obfuscated {
return p, nil
}
if p[0] == dissector.Handshake {
b, err := readClientHelloRecord(bytes.NewReader(p), c.host)
if err != nil {
return nil, err
}
c.obfuscated = true
return b, nil
}
buf := &bytes.Buffer{}
br := bufio.NewReader(bytes.NewReader(p))
for {
s, err := br.ReadString('\n')
if err != nil {
if err != io.EOF {
return nil, err
}
if s != "" {
buf.Write([]byte(s))
}
break
}
// end of HTTP header
if s == "\r\n" {
buf.Write([]byte(s))
// drain the remain bytes.
io.Copy(buf, br)
break
}
if strings.HasPrefix(s, "Host") {
s = strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(s, "Host:"), "\r\n"))
host := encodeServerName(s)
buf.WriteString("Host: " + c.host + "\r\n")
buf.WriteString("Gost-Target: " + host + "\r\n")
// drain the remain bytes.
io.Copy(buf, br)
break
}
buf.Write([]byte(s))
}
c.obfuscated = true
return buf.Bytes(), nil
}
func readClientHelloRecord(r io.Reader, host string) ([]byte, error) {
record, err := dissector.ReadRecord(r)
if err != nil {
return nil, err
}
clientHello := dissector.ClientHelloMsg{}
if err := clientHello.Decode(record.Opaque); err != nil {
return nil, err
}
for _, ext := range clientHello.Extensions {
if ext.Type() == dissector.ExtServerName {
snExtension := ext.(*dissector.ServerNameExtension)
if host != "" {
e, _ := dissector.NewExtension(0xFFFE, []byte(encodeServerName(snExtension.Name)))
clientHello.Extensions = append(clientHello.Extensions, e)
snExtension.Name = host
}
break
}
}
record.Opaque, err = clientHello.Encode()
if err != nil {
return nil, err
}
buf := &bytes.Buffer{}
if _, err := record.WriteTo(buf); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func encodeServerName(name string) string {
buf := &bytes.Buffer{}
binary.Write(buf, binary.BigEndian, crc32.ChecksumIEEE([]byte(name)))
buf.WriteString(base64.RawURLEncoding.EncodeToString([]byte(name)))
return base64.RawURLEncoding.EncodeToString(buf.Bytes())
}

View File

@ -1,46 +0,0 @@
package sni
import (
"context"
"net"
"github.com/go-gost/gost/pkg/connector"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
)
func init() {
registry.ConnectorRegistry().Register("sni", NewConnector)
}
type sniConnector struct {
md metadata
options connector.Options
}
func NewConnector(opts ...connector.Option) connector.Connector {
options := connector.Options{}
for _, opt := range opts {
opt(&options)
}
return &sniConnector{
options: options,
}
}
func (c *sniConnector) Init(md md.Metadata) (err error) {
return c.parseMetadata(md)
}
func (c *sniConnector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
log := c.options.Logger.WithFields(map[string]any{
"remote": conn.RemoteAddr().String(),
"local": conn.LocalAddr().String(),
"network": network,
"address": address,
})
log.Infof("connect %s/%s", address, network)
return &sniClientConn{Conn: conn, host: c.md.host}, nil
}

View File

@ -1,24 +0,0 @@
package sni
import (
"time"
mdata "github.com/go-gost/gost/pkg/metadata"
)
type metadata struct {
host string
connectTimeout time.Duration
}
func (c *sniConnector) parseMetadata(md mdata.Metadata) (err error) {
const (
host = "host"
connectTimeout = "timeout"
)
c.md.host = mdata.GetString(md, host)
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
return
}

View File

@ -9,9 +9,9 @@ import (
"time"
"github.com/go-gost/gosocks4"
"github.com/go-gost/gost/pkg/connector"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
"github.com/go-gost/gost/v3/pkg/connector"
md "github.com/go-gost/gost/v3/pkg/metadata"
"github.com/go-gost/gost/v3/pkg/registry"
)
func init() {

View File

@ -3,7 +3,7 @@ package v4
import (
"time"
mdata "github.com/go-gost/gost/pkg/metadata"
mdata "github.com/go-gost/gost/v3/pkg/metadata"
)
type metadata struct {

View File

@ -6,11 +6,11 @@ import (
"net"
"github.com/go-gost/gosocks5"
"github.com/go-gost/gost/pkg/common/util/mux"
"github.com/go-gost/gost/pkg/common/util/socks"
"github.com/go-gost/gost/pkg/common/util/udp"
"github.com/go-gost/gost/pkg/connector"
"github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/gost/v3/pkg/common/util/mux"
"github.com/go-gost/gost/v3/pkg/connector"
"github.com/go-gost/gost/v3/pkg/internal/util/socks"
"github.com/go-gost/gost/v3/pkg/internal/util/udp"
"github.com/go-gost/gost/v3/pkg/logger"
)
// Bind implements connector.Binder.

View File

@ -9,11 +9,11 @@ import (
"time"
"github.com/go-gost/gosocks5"
"github.com/go-gost/gost/pkg/common/util/socks"
"github.com/go-gost/gost/pkg/connector"
"github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
"github.com/go-gost/gost/v3/pkg/connector"
"github.com/go-gost/gost/v3/pkg/internal/util/socks"
"github.com/go-gost/gost/v3/pkg/logger"
md "github.com/go-gost/gost/v3/pkg/metadata"
"github.com/go-gost/gost/v3/pkg/registry"
)
func init() {

View File

@ -5,8 +5,8 @@ import (
"net"
"github.com/go-gost/gosocks5"
"github.com/go-gost/gost/pkg/common/util/mux"
"github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/gost/v3/pkg/common/util/mux"
"github.com/go-gost/gost/v3/pkg/logger"
)
type tcpListener struct {

View File

@ -3,7 +3,7 @@ package v5
import (
"time"
mdata "github.com/go-gost/gost/pkg/metadata"
mdata "github.com/go-gost/gost/v3/pkg/metadata"
)
type metadata struct {

View File

@ -6,8 +6,8 @@ import (
"net/url"
"github.com/go-gost/gosocks5"
"github.com/go-gost/gost/pkg/common/util/socks"
"github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/gost/v3/pkg/internal/util/socks"
"github.com/go-gost/gost/v3/pkg/logger"
)
type clientSelector struct {

View File

@ -1,111 +0,0 @@
package ss
import (
"context"
"fmt"
"net"
"time"
"github.com/go-gost/gosocks5"
"github.com/go-gost/gost/pkg/common/bufpool"
"github.com/go-gost/gost/pkg/common/util/ss"
"github.com/go-gost/gost/pkg/connector"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
"github.com/shadowsocks/go-shadowsocks2/core"
)
func init() {
registry.ConnectorRegistry().Register("ss", NewConnector)
}
type ssConnector struct {
cipher core.Cipher
md metadata
options connector.Options
}
func NewConnector(opts ...connector.Option) connector.Connector {
options := connector.Options{}
for _, opt := range opts {
opt(&options)
}
return &ssConnector{
options: options,
}
}
func (c *ssConnector) Init(md md.Metadata) (err error) {
if err = c.parseMetadata(md); err != nil {
return
}
if c.options.Auth != nil {
method := c.options.Auth.Username()
password, _ := c.options.Auth.Password()
c.cipher, err = ss.ShadowCipher(method, password, c.md.key)
}
return
}
func (c *ssConnector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
log := c.options.Logger.WithFields(map[string]any{
"remote": conn.RemoteAddr().String(),
"local": conn.LocalAddr().String(),
"network": network,
"address": address,
})
log.Infof("connect %s/%s", address, network)
switch network {
case "tcp", "tcp4", "tcp6":
if _, ok := conn.(net.PacketConn); ok {
err := fmt.Errorf("tcp over udp is unsupported")
log.Error(err)
return nil, err
}
default:
err := fmt.Errorf("network %s is unsupported", network)
log.Error(err)
return nil, err
}
addr := gosocks5.Addr{}
if err := addr.ParseFrom(address); err != nil {
log.Error(err)
return nil, err
}
rawaddr := bufpool.Get(512)
defer bufpool.Put(rawaddr)
n, err := addr.Encode(*rawaddr)
if err != nil {
log.Error("encoding addr: ", err)
return nil, err
}
if c.md.connectTimeout > 0 {
conn.SetDeadline(time.Now().Add(c.md.connectTimeout))
defer conn.SetDeadline(time.Time{})
}
if c.cipher != nil {
conn = c.cipher.StreamConn(conn)
}
var sc net.Conn
if c.md.noDelay {
sc = ss.ShadowConn(conn, nil)
// write the addr at once.
if _, err := sc.Write((*rawaddr)[:n]); err != nil {
return nil, err
}
} else {
// cache the header
sc = ss.ShadowConn(conn, (*rawaddr)[:n])
}
return sc, nil
}

View File

@ -1,27 +0,0 @@
package ss
import (
"time"
mdata "github.com/go-gost/gost/pkg/metadata"
)
type metadata struct {
key string
connectTimeout time.Duration
noDelay bool
}
func (c *ssConnector) parseMetadata(md mdata.Metadata) (err error) {
const (
key = "key"
connectTimeout = "timeout"
noDelay = "nodelay"
)
c.md.key = mdata.GetString(md, key)
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
c.md.noDelay = mdata.GetBool(md, noDelay)
return
}

View File

@ -1,95 +0,0 @@
package ss
import (
"context"
"fmt"
"net"
"time"
"github.com/go-gost/gost/pkg/common/util/socks"
"github.com/go-gost/gost/pkg/common/util/ss"
"github.com/go-gost/gost/pkg/connector"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
"github.com/shadowsocks/go-shadowsocks2/core"
)
func init() {
registry.ConnectorRegistry().Register("ssu", NewConnector)
}
type ssuConnector struct {
cipher core.Cipher
md metadata
options connector.Options
}
func NewConnector(opts ...connector.Option) connector.Connector {
options := connector.Options{}
for _, opt := range opts {
opt(&options)
}
return &ssuConnector{
options: options,
}
}
func (c *ssuConnector) Init(md md.Metadata) (err error) {
if err = c.parseMetadata(md); err != nil {
return
}
if c.options.Auth != nil {
method := c.options.Auth.Username()
password, _ := c.options.Auth.Password()
c.cipher, err = ss.ShadowCipher(method, password, c.md.key)
}
return
}
func (c *ssuConnector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
log := c.options.Logger.WithFields(map[string]any{
"remote": conn.RemoteAddr().String(),
"local": conn.LocalAddr().String(),
"network": network,
"address": address,
})
log.Infof("connect %s/%s", address, network)
switch network {
case "udp", "udp4", "udp6":
default:
err := fmt.Errorf("network %s is unsupported", network)
log.Error(err)
return nil, err
}
if c.md.connectTimeout > 0 {
conn.SetDeadline(time.Now().Add(c.md.connectTimeout))
defer conn.SetDeadline(time.Time{})
}
taddr, _ := net.ResolveUDPAddr(network, address)
if taddr == nil {
taddr = &net.UDPAddr{}
}
pc, ok := conn.(net.PacketConn)
if ok {
if c.cipher != nil {
pc = c.cipher.PacketConn(pc)
}
// standard UDP relay
return ss.UDPClientConn(pc, conn.RemoteAddr(), taddr, c.md.bufferSize), nil
}
if c.cipher != nil {
conn = ss.ShadowConn(c.cipher.StreamConn(conn), nil)
}
// UDP over TCP
return socks.UDPTunClientConn(conn, taddr), nil
}

View File

@ -1,33 +0,0 @@
package ss
import (
"math"
"time"
mdata "github.com/go-gost/gost/pkg/metadata"
)
type metadata struct {
key string
connectTimeout time.Duration
bufferSize int
}
func (c *ssuConnector) parseMetadata(md mdata.Metadata) (err error) {
const (
key = "key"
connectTimeout = "timeout"
bufferSize = "bufferSize" // udp buffer size
)
c.md.key = mdata.GetString(md, key)
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
if bs := mdata.GetInt(md, bufferSize); bs > 0 {
c.md.bufferSize = int(math.Min(math.Max(float64(bs), 512), 64*1024))
} else {
c.md.bufferSize = 1024
}
return
}

View File

@ -1,80 +0,0 @@
package sshd
import (
"context"
"errors"
"net"
"github.com/go-gost/gost/pkg/connector"
ssh_util "github.com/go-gost/gost/pkg/internal/util/ssh"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
)
func init() {
registry.ConnectorRegistry().Register("sshd", NewConnector)
}
type sshdConnector struct {
options connector.Options
}
func NewConnector(opts ...connector.Option) connector.Connector {
options := connector.Options{}
for _, opt := range opts {
opt(&options)
}
return &sshdConnector{
options: options,
}
}
func (c *sshdConnector) Init(md md.Metadata) (err error) {
return nil
}
func (c *sshdConnector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
log := c.options.Logger.WithFields(map[string]any{
"remote": conn.RemoteAddr().String(),
"local": conn.LocalAddr().String(),
"network": network,
"address": address,
})
log.Infof("connect %s/%s", address, network)
cc, ok := conn.(*ssh_util.ClientConn)
if !ok {
return nil, errors.New("ssh: invalid connection")
}
conn, err := cc.Client().Dial(network, address)
if err != nil {
log.Error(err)
return nil, err
}
return conn, nil
}
// Bind implements connector.Binder.
func (c *sshdConnector) Bind(ctx context.Context, conn net.Conn, network, address string, opts ...connector.BindOption) (net.Listener, error) {
log := c.options.Logger.WithFields(map[string]any{
"remote": conn.RemoteAddr().String(),
"local": conn.LocalAddr().String(),
"network": network,
"address": address,
})
log.Infof("bind on %s/%s", address, network)
cc, ok := conn.(*ssh_util.ClientConn)
if !ok {
return nil, errors.New("ssh: invalid connection")
}
if host, port, _ := net.SplitHostPort(address); host == "" {
address = net.JoinHostPort("0.0.0.0", port)
}
return cc.Client().Listen(network, address)
}

View File

@ -4,7 +4,7 @@ import (
"context"
"net"
"github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/v3/pkg/metadata"
)
// Transporter is responsible for dialing to the proxy server.

View File

@ -1,21 +0,0 @@
package ftcp
import "net"
type fakeTCPConn struct {
raddr net.Addr
net.PacketConn
}
func (c *fakeTCPConn) Read(b []byte) (n int, err error) {
n, _, err = c.ReadFrom(b)
return
}
func (c *fakeTCPConn) Write(b []byte) (n int, err error) {
return c.WriteTo(b, c.raddr)
}
func (c *fakeTCPConn) RemoteAddr() net.Addr {
return c.raddr
}

View File

@ -1,51 +0,0 @@
package ftcp
import (
"context"
"net"
"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"
"github.com/xtaci/tcpraw"
)
func init() {
registry.DialerRegistry().Register("ftcp", NewDialer)
}
type ftcpDialer struct {
md metadata
logger logger.Logger
}
func NewDialer(opts ...dialer.Option) dialer.Dialer {
options := &dialer.Options{}
for _, opt := range opts {
opt(options)
}
return &ftcpDialer{
logger: options.Logger,
}
}
func (d *ftcpDialer) Init(md md.Metadata) (err error) {
return d.parseMetadata(md)
}
func (d *ftcpDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (conn net.Conn, err error) {
raddr, er := net.ResolveTCPAddr("tcp", addr)
if er != nil {
return nil, er
}
c, err := tcpraw.Dial("tcp", addr)
if err != nil {
return
}
return &fakeTCPConn{
raddr: raddr,
PacketConn: c,
}, nil
}

View File

@ -1,23 +0,0 @@
package ftcp
import (
"time"
md "github.com/go-gost/gost/pkg/metadata"
)
const (
dialTimeout = "dialTimeout"
)
const (
defaultDialTimeout = 5 * time.Second
)
type metadata struct {
dialTimeout time.Duration
}
func (d *ftcpDialer) parseMetadata(md md.Metadata) (err error) {
return
}

View File

@ -1,92 +0,0 @@
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")}
}

View File

@ -1,113 +0,0 @@
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"
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.DialerRegistry().Register("grpc", NewDialer)
}
type grpcDialer struct {
clients map[string]pb.GostTunelClient
clientMutex sync.Mutex
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),
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
}
if h, _, _ := net.SplitHostPort(host); h != "" {
host = h
}
grpcOpts := []grpc.DialOption{
// grpc.WithBlock(),
grpc.WithContextDialer(func(c context.Context, s string) (net.Conn, error) {
return options.NetDialer.Dial(c, "tcp", s)
}),
grpc.WithAuthority(host),
grpc.WithConnectParams(grpc.ConnectParams{
Backoff: backoff.DefaultConfig,
MinConnectTimeout: 10 * time.Second,
}),
grpc.FailOnNonTempDialError(true),
}
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.options.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
}

View File

@ -1,22 +0,0 @@
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

@ -7,12 +7,12 @@ import (
"sync"
"time"
net_dialer "github.com/go-gost/gost/pkg/common/net/dialer"
"github.com/go-gost/gost/pkg/dialer"
http2_util "github.com/go-gost/gost/pkg/internal/util/http2"
"github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
net_dialer "github.com/go-gost/gost/v3/pkg/common/net/dialer"
"github.com/go-gost/gost/v3/pkg/dialer"
http2_util "github.com/go-gost/gost/v3/pkg/internal/util/http2"
"github.com/go-gost/gost/v3/pkg/logger"
md "github.com/go-gost/gost/v3/pkg/metadata"
"github.com/go-gost/gost/v3/pkg/registry"
)
func init() {

View File

@ -12,10 +12,10 @@ import (
"sync"
"time"
"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"
"github.com/go-gost/gost/v3/pkg/dialer"
"github.com/go-gost/gost/v3/pkg/logger"
md "github.com/go-gost/gost/v3/pkg/metadata"
"github.com/go-gost/gost/v3/pkg/registry"
"golang.org/x/net/http2"
)

View File

@ -1,7 +1,7 @@
package h2
import (
mdata "github.com/go-gost/gost/pkg/metadata"
mdata "github.com/go-gost/gost/v3/pkg/metadata"
)
type metadata struct {

View File

@ -1,7 +1,7 @@
package http2
import (
mdata "github.com/go-gost/gost/pkg/metadata"
mdata "github.com/go-gost/gost/v3/pkg/metadata"
)
type metadata struct {

View File

@ -1,107 +0,0 @@
package http3
import (
"context"
"crypto/tls"
"net"
"net/http"
"sync"
"github.com/go-gost/gost/pkg/dialer"
pht_util "github.com/go-gost/gost/pkg/internal/util/pht"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
"github.com/lucas-clemente/quic-go"
"github.com/lucas-clemente/quic-go/http3"
)
func init() {
registry.DialerRegistry().Register("http3", NewDialer)
registry.DialerRegistry().Register("h3", NewDialer)
}
type http3Dialer struct {
clients map[string]*pht_util.Client
clientMutex sync.Mutex
md metadata
options dialer.Options
}
func NewDialer(opts ...dialer.Option) dialer.Dialer {
options := dialer.Options{}
for _, opt := range opts {
opt(&options)
}
return &http3Dialer{
clients: make(map[string]*pht_util.Client),
options: options,
}
}
func (d *http3Dialer) Init(md md.Metadata) (err error) {
if err = d.parseMetadata(md); err != nil {
return
}
return nil
}
func (d *http3Dialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (net.Conn, error) {
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
}
if h, _, _ := net.SplitHostPort(host); h != "" {
host = h
}
client = &pht_util.Client{
Host: host,
Client: &http.Client{
// Timeout: 60 * time.Second,
Transport: &http3.RoundTripper{
TLSClientConfig: d.options.TLSConfig,
Dial: func(network, adr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlySession, error) {
// d.options.Logger.Infof("dial: %s/%s, %s", addr, network, host)
udpAddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil {
return nil, err
}
udpConn, err := options.NetDialer.Dial(context.Background(), "udp", "")
if err != nil {
return nil, err
}
return quic.DialEarly(udpConn.(net.PacketConn), udpAddr, host, tlsCfg, cfg)
},
},
},
AuthorizePath: d.md.authorizePath,
PushPath: d.md.pushPath,
PullPath: d.md.pullPath,
TLSEnabled: true,
Logger: d.options.Logger,
}
d.clients[addr] = client
}
return client.Dial(ctx, addr)
}
// Multiplex implements dialer.Multiplexer interface.
func (d *http3Dialer) Multiplex() bool {
return true
}

View File

@ -1,52 +0,0 @@
package http3
import (
"strings"
"time"
mdata "github.com/go-gost/gost/pkg/metadata"
)
const (
dialTimeout = "dialTimeout"
defaultAuthorizePath = "/authorize"
defaultPushPath = "/push"
defaultPullPath = "/pull"
)
const (
defaultDialTimeout = 5 * time.Second
)
type metadata struct {
dialTimeout time.Duration
authorizePath string
pushPath string
pullPath string
host string
}
func (d *http3Dialer) parseMetadata(md mdata.Metadata) (err error) {
const (
authorizePath = "authorizePath"
pushPath = "pushPath"
pullPath = "pullPath"
host = "host"
)
d.md.authorizePath = mdata.GetString(md, authorizePath)
if !strings.HasPrefix(d.md.authorizePath, "/") {
d.md.authorizePath = defaultAuthorizePath
}
d.md.pushPath = mdata.GetString(md, pushPath)
if !strings.HasPrefix(d.md.pushPath, "/") {
d.md.pushPath = defaultPushPath
}
d.md.pullPath = mdata.GetString(md, pullPath)
if !strings.HasPrefix(d.md.pullPath, "/") {
d.md.pullPath = defaultPullPath
}
d.md.host = mdata.GetString(md, host)
return
}

View File

@ -1,42 +0,0 @@
package quic
import (
"context"
"net"
"github.com/lucas-clemente/quic-go"
)
type quicSession struct {
session quic.Session
}
func (session *quicSession) GetConn() (*quicConn, error) {
stream, err := session.session.OpenStreamSync(context.Background())
if err != nil {
return nil, err
}
return &quicConn{
Stream: stream,
laddr: session.session.LocalAddr(),
raddr: session.session.RemoteAddr(),
}, nil
}
func (session *quicSession) Close() error {
return session.session.CloseWithError(quic.ApplicationErrorCode(0), "closed")
}
type quicConn struct {
quic.Stream
laddr net.Addr
raddr net.Addr
}
func (c *quicConn) LocalAddr() net.Addr {
return c.laddr
}
func (c *quicConn) RemoteAddr() net.Addr {
return c.raddr
}

View File

@ -1,130 +0,0 @@
package quic
import (
"context"
"math"
"math/rand"
"net"
"sync"
"time"
"github.com/go-gost/gost/pkg/dialer"
icmp_pkg "github.com/go-gost/gost/pkg/internal/util/icmp"
"github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
"github.com/lucas-clemente/quic-go"
"golang.org/x/net/icmp"
)
func init() {
registry.DialerRegistry().Register("icmp", NewDialer)
}
type icmpDialer struct {
sessions map[string]*quicSession
sessionMutex 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 &icmpDialer{
sessions: make(map[string]*quicSession),
logger: options.Logger,
options: options,
}
}
func (d *icmpDialer) Init(md md.Metadata) (err error) {
if err = d.parseMetadata(md); err != nil {
return
}
return nil
}
func (d *icmpDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (conn net.Conn, err error) {
if _, _, err := net.SplitHostPort(addr); err != nil {
addr = net.JoinHostPort(addr, "0")
}
raddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil {
return nil, err
}
d.sessionMutex.Lock()
defer d.sessionMutex.Unlock()
session, ok := d.sessions[addr]
if !ok {
options := &dialer.DialOptions{}
for _, opt := range opts {
opt(options)
}
var pc net.PacketConn
pc, err = icmp.ListenPacket("ip4:icmp", "")
if err != nil {
return
}
id := raddr.Port
if id == 0 {
id = rand.New(rand.NewSource(time.Now().UnixNano())).Intn(math.MaxUint16) + 1
raddr.Port = id
}
pc = icmp_pkg.ClientConn(pc, id)
session, err = d.initSession(ctx, raddr, pc)
if err != nil {
d.logger.Error(err)
pc.Close()
return nil, err
}
d.sessions[addr] = session
}
conn, err = session.GetConn()
if err != nil {
session.Close()
delete(d.sessions, addr)
return nil, err
}
return
}
func (d *icmpDialer) initSession(ctx context.Context, addr net.Addr, conn net.PacketConn) (*quicSession, error) {
quicConfig := &quic.Config{
KeepAlive: d.md.keepAlive,
HandshakeIdleTimeout: d.md.handshakeTimeout,
MaxIdleTimeout: d.md.maxIdleTimeout,
Versions: []quic.VersionNumber{
quic.Version1,
quic.VersionDraft29,
},
}
tlsCfg := d.options.TLSConfig
tlsCfg.NextProtos = []string{"http/3", "quic/v1"}
session, err := quic.DialContext(ctx, conn, addr, addr.String(), tlsCfg, quicConfig)
if err != nil {
return nil, err
}
return &quicSession{session: session}, nil
}
// Multiplex implements dialer.Multiplexer interface.
func (d *icmpDialer) Multiplex() bool {
return true
}

View File

@ -1,29 +0,0 @@
package quic
import (
"time"
mdata "github.com/go-gost/gost/pkg/metadata"
)
type metadata struct {
keepAlive bool
maxIdleTimeout time.Duration
handshakeTimeout time.Duration
}
func (d *icmpDialer) parseMetadata(md mdata.Metadata) (err error) {
const (
keepAlive = "keepAlive"
handshakeTimeout = "handshakeTimeout"
maxIdleTimeout = "maxIdleTimeout"
)
d.md.handshakeTimeout = mdata.GetDuration(md, handshakeTimeout)
d.md.keepAlive = mdata.GetBool(md, keepAlive)
d.md.handshakeTimeout = mdata.GetDuration(md, handshakeTimeout)
d.md.maxIdleTimeout = mdata.GetDuration(md, maxIdleTimeout)
return
}

View File

@ -1,55 +0,0 @@
package kcp
import (
"net"
"github.com/xtaci/smux"
)
type muxSession struct {
session *smux.Session
}
func (session *muxSession) GetConn() (net.Conn, error) {
return session.session.OpenStream()
}
func (session *muxSession) Accept() (net.Conn, error) {
return session.session.AcceptStream()
}
func (session *muxSession) Close() error {
if session.session == nil {
return nil
}
return session.session.Close()
}
func (session *muxSession) IsClosed() bool {
if session.session == nil {
return true
}
return session.session.IsClosed()
}
func (session *muxSession) NumStreams() int {
return session.session.NumStreams()
}
type fakeTCPConn struct {
raddr net.Addr
net.PacketConn
}
func (c *fakeTCPConn) Read(b []byte) (n int, err error) {
n, _, err = c.ReadFrom(b)
return
}
func (c *fakeTCPConn) Write(b []byte) (n int, err error) {
return c.WriteTo(b, c.raddr)
}
func (c *fakeTCPConn) RemoteAddr() net.Addr {
return c.raddr
}

View File

@ -1,165 +0,0 @@
package kcp
import (
"context"
"errors"
"net"
"sync"
"time"
kcp_util "github.com/go-gost/gost/pkg/common/util/kcp"
"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"
"github.com/xtaci/kcp-go/v5"
"github.com/xtaci/smux"
"github.com/xtaci/tcpraw"
)
func init() {
registry.DialerRegistry().Register("kcp", NewDialer)
}
type kcpDialer struct {
sessions map[string]*muxSession
sessionMutex 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 &kcpDialer{
sessions: make(map[string]*muxSession),
logger: options.Logger,
options: options,
}
}
func (d *kcpDialer) Init(md md.Metadata) (err error) {
if err = d.parseMetadata(md); err != nil {
return
}
d.md.config.Init()
return nil
}
func (d *kcpDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (conn net.Conn, err error) {
raddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil {
return nil, err
}
d.sessionMutex.Lock()
defer d.sessionMutex.Unlock()
session, ok := d.sessions[addr]
if session != nil && session.IsClosed() {
delete(d.sessions, addr) // session is dead
ok = false
}
if !ok {
var options dialer.DialOptions
for _, opt := range opts {
opt(&options)
}
var pc net.PacketConn
if d.md.config.TCP {
pc, err = tcpraw.Dial("tcp", addr)
if err != nil {
return nil, err
}
pc = &fakeTCPConn{
raddr: raddr,
PacketConn: pc,
}
} else {
c, err := options.NetDialer.Dial(ctx, "udp", "")
if err != nil {
return nil, err
}
var ok bool
pc, ok = c.(net.PacketConn)
if !ok {
c.Close()
return nil, errors.New("quic: wrong connection type")
}
}
session, err = d.initSession(ctx, raddr, pc)
if err != nil {
d.logger.Error(err)
pc.Close()
return nil, err
}
d.sessions[addr] = session
}
conn, err = session.GetConn()
if err != nil {
session.Close()
delete(d.sessions, addr)
return nil, err
}
return
}
func (d *kcpDialer) initSession(ctx context.Context, addr net.Addr, conn net.PacketConn) (*muxSession, error) {
config := d.md.config
kcpconn, err := kcp.NewConn(addr.String(),
kcp_util.BlockCrypt(config.Key, config.Crypt, kcp_util.DefaultSalt),
config.DataShard, config.ParityShard, conn)
if err != nil {
return nil, err
}
kcpconn.SetStreamMode(true)
kcpconn.SetWriteDelay(false)
kcpconn.SetNoDelay(config.NoDelay, config.Interval, config.Resend, config.NoCongestion)
kcpconn.SetWindowSize(config.SndWnd, config.RcvWnd)
kcpconn.SetMtu(config.MTU)
kcpconn.SetACKNoDelay(config.AckNodelay)
if config.DSCP > 0 {
if er := kcpconn.SetDSCP(config.DSCP); er != nil {
d.logger.Warn("SetDSCP: ", er)
}
}
if er := kcpconn.SetReadBuffer(config.SockBuf); er != nil {
d.logger.Warn("SetReadBuffer: ", er)
}
if er := kcpconn.SetWriteBuffer(config.SockBuf); er != nil {
d.logger.Warn("SetWriteBuffer: ", er)
}
// stream multiplex
smuxConfig := smux.DefaultConfig()
smuxConfig.MaxReceiveBuffer = config.SockBuf
smuxConfig.KeepAliveInterval = time.Duration(config.KeepAlive) * time.Second
var cc net.Conn = kcpconn
if !config.NoComp {
cc = kcp_util.CompStreamConn(kcpconn)
}
session, err := smux.Client(cc, smuxConfig)
if err != nil {
return nil, err
}
return &muxSession{session: session}, nil
}
// Multiplex implements dialer.Multiplexer interface.
func (d *kcpDialer) Multiplex() bool {
return true
}

View File

@ -1,39 +0,0 @@
package kcp
import (
"encoding/json"
"time"
kcp_util "github.com/go-gost/gost/pkg/common/util/kcp"
mdata "github.com/go-gost/gost/pkg/metadata"
)
type metadata struct {
handshakeTimeout time.Duration
config *kcp_util.Config
}
func (d *kcpDialer) parseMetadata(md mdata.Metadata) (err error) {
const (
config = "config"
handshakeTimeout = "handshakeTimeout"
)
if m := mdata.GetStringMap(md, config); len(m) > 0 {
b, err := json.Marshal(m)
if err != nil {
return err
}
cfg := &kcp_util.Config{}
if err := json.Unmarshal(b, cfg); err != nil {
return err
}
d.md.config = cfg
}
if d.md.config == nil {
d.md.config = kcp_util.DefaultConfig
}
d.md.handshakeTimeout = mdata.GetDuration(md, handshakeTimeout)
return
}

View File

@ -1,144 +0,0 @@
package http
import (
"bufio"
"bytes"
"crypto/rand"
"encoding/base64"
"io"
"net"
"net/http"
"net/http/httputil"
"net/url"
"sync"
"github.com/go-gost/gost/pkg/logger"
)
type obfsHTTPConn struct {
net.Conn
host string
rbuf bytes.Buffer
wbuf bytes.Buffer
headerDrained bool
handshaked bool
handshakeMutex sync.Mutex
header http.Header
logger logger.Logger
}
func (c *obfsHTTPConn) Handshake() (err error) {
c.handshakeMutex.Lock()
defer c.handshakeMutex.Unlock()
if c.handshaked {
return nil
}
err = c.handshake()
if err != nil {
return
}
c.handshaked = true
return nil
}
func (c *obfsHTTPConn) handshake() (err error) {
r := &http.Request{
Method: http.MethodGet,
ProtoMajor: 1,
ProtoMinor: 1,
URL: &url.URL{Scheme: "http", Host: c.host},
Header: c.header,
}
if r.Header == nil {
r.Header = http.Header{}
}
r.Header.Set("Connection", "Upgrade")
r.Header.Set("Upgrade", "websocket")
key, _ := c.generateChallengeKey()
r.Header.Set("Sec-WebSocket-Key", key)
// cache the request header
if err = r.Write(&c.wbuf); err != nil {
return
}
if c.logger.IsLevelEnabled(logger.DebugLevel) {
dump, _ := httputil.DumpRequest(r, false)
c.logger.Debug(string(dump))
}
return nil
}
func (c *obfsHTTPConn) Read(b []byte) (n int, err error) {
if err = c.Handshake(); err != nil {
return
}
if err = c.drainHeader(); err != nil {
return
}
if c.rbuf.Len() > 0 {
return c.rbuf.Read(b)
}
return c.Conn.Read(b)
}
func (c *obfsHTTPConn) drainHeader() (err error) {
if c.headerDrained {
return
}
c.headerDrained = true
br := bufio.NewReader(c.Conn)
// drain and discard the response header
var line string
var buf bytes.Buffer
for {
line, err = br.ReadString('\n')
if err != nil {
return
}
buf.WriteString(line)
if line == "\r\n" {
break
}
}
if c.logger.IsLevelEnabled(logger.DebugLevel) {
c.logger.Debug(buf.String())
}
// cache the extra data for next read.
var b []byte
b, err = br.Peek(br.Buffered())
if len(b) > 0 {
_, err = c.rbuf.Write(b)
}
return
}
func (c *obfsHTTPConn) Write(b []byte) (n int, err error) {
if err = c.Handshake(); err != nil {
return
}
if c.wbuf.Len() > 0 {
c.wbuf.Write(b) // append the data to the cached header
_, err = c.wbuf.WriteTo(c.Conn)
n = len(b) // exclude the header length
return
}
return c.Conn.Write(b)
}
func (c *obfsHTTPConn) generateChallengeKey() (string, error) {
p := make([]byte, 16)
if _, err := io.ReadFull(rand.Reader, p); err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(p), nil
}

View File

@ -1,68 +0,0 @@
package http
import (
"context"
"net"
"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"
)
func init() {
registry.DialerRegistry().Register("ohttp", NewDialer)
}
type obfsHTTPDialer struct {
md metadata
logger logger.Logger
}
func NewDialer(opts ...dialer.Option) dialer.Dialer {
options := &dialer.Options{}
for _, opt := range opts {
opt(options)
}
return &obfsHTTPDialer{
logger: options.Logger,
}
}
func (d *obfsHTTPDialer) Init(md md.Metadata) (err error) {
return d.parseMetadata(md)
}
func (d *obfsHTTPDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (net.Conn, error) {
options := &dialer.DialOptions{}
for _, opt := range opts {
opt(options)
}
conn, err := options.NetDialer.Dial(ctx, "tcp", addr)
if err != nil {
d.logger.Error(err)
}
return conn, err
}
// Handshake implements dialer.Handshaker
func (d *obfsHTTPDialer) Handshake(ctx context.Context, conn net.Conn, options ...dialer.HandshakeOption) (net.Conn, error) {
opts := &dialer.HandshakeOptions{}
for _, option := range options {
option(opts)
}
host := d.md.host
if host == "" {
host = opts.Addr
}
return &obfsHTTPConn{
Conn: conn,
host: host,
header: d.md.header,
logger: d.logger,
}, nil
}

View File

@ -1,29 +0,0 @@
package http
import (
"net/http"
mdata "github.com/go-gost/gost/pkg/metadata"
)
type metadata struct {
host string
header http.Header
}
func (d *obfsHTTPDialer) parseMetadata(md mdata.Metadata) (err error) {
const (
header = "header"
host = "host"
)
if m := mdata.GetStringMapString(md, header); len(m) > 0 {
h := http.Header{}
for k, v := range m {
h.Add(k, v)
}
d.md.header = h
}
d.md.host = mdata.GetString(md, host)
return
}

View File

@ -1,266 +0,0 @@
package tls
import (
"bytes"
"crypto/rand"
"crypto/tls"
"errors"
"net"
"sync"
"time"
dissector "github.com/go-gost/tls-dissector"
)
const (
maxTLSDataLen = 16384
)
var (
cipherSuites = []uint16{
0xc02c, 0xc030, 0x009f, 0xcca9, 0xcca8, 0xccaa, 0xc02b, 0xc02f,
0x009e, 0xc024, 0xc028, 0x006b, 0xc023, 0xc027, 0x0067, 0xc00a,
0xc014, 0x0039, 0xc009, 0xc013, 0x0033, 0x009d, 0x009c, 0x003d,
0x003c, 0x0035, 0x002f, 0x00ff,
}
compressionMethods = []uint8{0x00}
algorithms = []uint16{
0x0601, 0x0602, 0x0603, 0x0501, 0x0502, 0x0503, 0x0401, 0x0402,
0x0403, 0x0301, 0x0302, 0x0303, 0x0201, 0x0202, 0x0203,
}
tlsRecordTypes = []uint8{0x16, 0x14, 0x16, 0x17}
tlsVersionMinors = []uint8{0x01, 0x03, 0x03, 0x03}
ErrBadType = errors.New("bad type")
ErrBadMajorVersion = errors.New("bad major version")
ErrBadMinorVersion = errors.New("bad minor version")
ErrMaxDataLen = errors.New("bad tls data len")
)
const (
tlsRecordStateType = iota
tlsRecordStateVersion0
tlsRecordStateVersion1
tlsRecordStateLength0
tlsRecordStateLength1
tlsRecordStateData
)
type obfsTLSParser struct {
step uint8
state uint8
length uint16
}
func (r *obfsTLSParser) Parse(b []byte) (int, error) {
i := 0
last := 0
length := len(b)
for i < length {
ch := b[i]
switch r.state {
case tlsRecordStateType:
if tlsRecordTypes[r.step] != ch {
return 0, ErrBadType
}
r.state = tlsRecordStateVersion0
i++
case tlsRecordStateVersion0:
if ch != 0x03 {
return 0, ErrBadMajorVersion
}
r.state = tlsRecordStateVersion1
i++
case tlsRecordStateVersion1:
if ch != tlsVersionMinors[r.step] {
return 0, ErrBadMinorVersion
}
r.state = tlsRecordStateLength0
i++
case tlsRecordStateLength0:
r.length = uint16(ch) << 8
r.state = tlsRecordStateLength1
i++
case tlsRecordStateLength1:
r.length |= uint16(ch)
if r.step == 0 {
r.length = 91
} else if r.step == 1 {
r.length = 1
} else if r.length > maxTLSDataLen {
return 0, ErrMaxDataLen
}
if r.length > 0 {
r.state = tlsRecordStateData
} else {
r.state = tlsRecordStateType
r.step++
}
i++
case tlsRecordStateData:
left := uint16(length - i)
if left > r.length {
left = r.length
}
if r.step >= 2 {
skip := i - last
copy(b[last:], b[i:length])
length -= int(skip)
last += int(left)
i = last
} else {
i += int(left)
}
r.length -= left
if r.length == 0 {
if r.step < 3 {
r.step++
}
r.state = tlsRecordStateType
}
}
}
if last == 0 {
return 0, nil
} else if last < length {
length -= last
}
return length, nil
}
type obfsTLSConn struct {
net.Conn
wbuf bytes.Buffer
host string
handshaked chan struct{}
parser obfsTLSParser
handshakeMutex sync.Mutex
}
func (c *obfsTLSConn) Handshaked() bool {
select {
case <-c.handshaked:
return true
default:
return false
}
}
func (c *obfsTLSConn) Handshake(payload []byte) (err error) {
c.handshakeMutex.Lock()
defer c.handshakeMutex.Unlock()
if c.Handshaked() {
return
}
if err = c.handshake(payload); err != nil {
return
}
close(c.handshaked)
return nil
}
func (c *obfsTLSConn) handshake(payload []byte) error {
clientMsg := &dissector.ClientHelloMsg{
Version: tls.VersionTLS12,
SessionID: make([]byte, 32),
CipherSuites: cipherSuites,
CompressionMethods: compressionMethods,
Extensions: []dissector.Extension{
&dissector.SessionTicketExtension{
Data: payload,
},
&dissector.ServerNameExtension{
Name: c.host,
},
&dissector.ECPointFormatsExtension{
Formats: []uint8{0x01, 0x00, 0x02},
},
&dissector.SupportedGroupsExtension{
Groups: []uint16{0x001d, 0x0017, 0x0019, 0x0018},
},
&dissector.SignatureAlgorithmsExtension{
Algorithms: algorithms,
},
&dissector.EncryptThenMacExtension{},
&dissector.ExtendedMasterSecretExtension{},
},
}
clientMsg.Random.Time = uint32(time.Now().Unix())
rand.Read(clientMsg.Random.Opaque[:])
rand.Read(clientMsg.SessionID)
b, err := clientMsg.Encode()
if err != nil {
return err
}
record := &dissector.Record{
Type: dissector.Handshake,
Version: tls.VersionTLS10,
Opaque: b,
}
if _, err := record.WriteTo(c.Conn); err != nil {
return err
}
return err
}
func (c *obfsTLSConn) Read(b []byte) (n int, err error) {
<-c.handshaked
n, err = c.Conn.Read(b)
if err != nil {
return
}
if n > 0 {
n, err = c.parser.Parse(b[:n])
}
return
}
func (c *obfsTLSConn) Write(b []byte) (n int, err error) {
n = len(b)
if !c.Handshaked() {
if err = c.Handshake(b); err != nil {
return
}
return
}
for len(b) > 0 {
data := b
if len(b) > maxTLSDataLen {
data = b[:maxTLSDataLen]
b = b[maxTLSDataLen:]
} else {
b = b[:0]
}
record := &dissector.Record{
Type: dissector.AppData,
Version: tls.VersionTLS12,
Opaque: data,
}
if c.wbuf.Len() > 0 {
record.Type = dissector.Handshake
record.WriteTo(&c.wbuf)
_, err = c.wbuf.WriteTo(c.Conn)
return
}
if _, err = record.WriteTo(c.Conn); err != nil {
return
}
}
return
}

View File

@ -1,67 +0,0 @@
package tls
import (
"context"
"net"
"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"
)
func init() {
registry.DialerRegistry().Register("otls", NewDialer)
}
type obfsTLSDialer struct {
md metadata
logger logger.Logger
}
func NewDialer(opts ...dialer.Option) dialer.Dialer {
options := &dialer.Options{}
for _, opt := range opts {
opt(options)
}
return &obfsTLSDialer{
logger: options.Logger,
}
}
func (d *obfsTLSDialer) Init(md md.Metadata) (err error) {
return d.parseMetadata(md)
}
func (d *obfsTLSDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (net.Conn, error) {
options := &dialer.DialOptions{}
for _, opt := range opts {
opt(options)
}
conn, err := options.NetDialer.Dial(ctx, "tcp", addr)
if err != nil {
d.logger.Error(err)
}
return conn, err
}
// Handshake implements dialer.Handshaker
func (d *obfsTLSDialer) Handshake(ctx context.Context, conn net.Conn, options ...dialer.HandshakeOption) (net.Conn, error) {
opts := &dialer.HandshakeOptions{}
for _, option := range options {
option(opts)
}
host := d.md.host
if host == "" {
host = opts.Addr
}
return &obfsTLSConn{
Conn: conn,
host: host,
handshaked: make(chan struct{}),
}, nil
}

View File

@ -1,18 +0,0 @@
package tls
import (
mdata "github.com/go-gost/gost/pkg/metadata"
)
type metadata struct {
host string
}
func (d *obfsTLSDialer) parseMetadata(md mdata.Metadata) (err error) {
const (
host = "host"
)
d.md.host = mdata.GetString(md, host)
return
}

View File

@ -4,8 +4,8 @@ import (
"crypto/tls"
"net/url"
"github.com/go-gost/gost/pkg/common/net/dialer"
"github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/gost/v3/pkg/common/net/dialer"
"github.com/go-gost/gost/v3/pkg/logger"
)
type Options struct {

View File

@ -1,114 +0,0 @@
package pht
import (
"context"
"net"
"net/http"
"sync"
"time"
"github.com/go-gost/gost/pkg/dialer"
pht_util "github.com/go-gost/gost/pkg/internal/util/pht"
"github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
)
func init() {
registry.DialerRegistry().Register("pht", NewDialer)
registry.DialerRegistry().Register("phts", NewTLSDialer)
}
type phtDialer struct {
clients map[string]*pht_util.Client
clientMutex sync.Mutex
tlsEnabled bool
md metadata
logger logger.Logger
options dialer.Options
}
func NewDialer(opts ...dialer.Option) dialer.Dialer {
options := dialer.Options{}
for _, opt := range opts {
opt(&options)
}
return &phtDialer{
clients: make(map[string]*pht_util.Client),
options: options,
}
}
func NewTLSDialer(opts ...dialer.Option) dialer.Dialer {
options := dialer.Options{}
for _, opt := range opts {
opt(&options)
}
return &phtDialer{
tlsEnabled: true,
clients: make(map[string]*pht_util.Client),
options: options,
}
}
func (d *phtDialer) Init(md md.Metadata) (err error) {
if err = d.parseMetadata(md); err != nil {
return
}
return nil
}
func (d *phtDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (net.Conn, error) {
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
}
if h, _, _ := net.SplitHostPort(host); h != "" {
host = h
}
tr := &http.Transport{
// Proxy: http.ProxyFromEnvironment,
DialContext: func(ctx context.Context, network, adr string) (net.Conn, error) {
return options.NetDialer.Dial(ctx, network, addr)
},
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
if d.tlsEnabled {
tr.TLSClientConfig = d.options.TLSConfig
}
client = &pht_util.Client{
Host: host,
Client: &http.Client{
// Timeout: 60 * time.Second,
Transport: tr,
},
AuthorizePath: d.md.authorizePath,
PushPath: d.md.pushPath,
PullPath: d.md.pullPath,
TLSEnabled: d.tlsEnabled,
Logger: d.options.Logger,
}
d.clients[addr] = client
}
return client.Dial(ctx, addr)
}

View File

@ -1,52 +0,0 @@
package pht
import (
"strings"
"time"
mdata "github.com/go-gost/gost/pkg/metadata"
)
const (
dialTimeout = "dialTimeout"
defaultAuthorizePath = "/authorize"
defaultPushPath = "/push"
defaultPullPath = "/pull"
)
const (
defaultDialTimeout = 5 * time.Second
)
type metadata struct {
dialTimeout time.Duration
authorizePath string
pushPath string
pullPath string
host string
}
func (d *phtDialer) parseMetadata(md mdata.Metadata) (err error) {
const (
authorizePath = "authorizePath"
pushPath = "pushPath"
pullPath = "pullPath"
host = "host"
)
d.md.authorizePath = mdata.GetString(md, authorizePath)
if !strings.HasPrefix(d.md.authorizePath, "/") {
d.md.authorizePath = defaultAuthorizePath
}
d.md.pushPath = mdata.GetString(md, pushPath)
if !strings.HasPrefix(d.md.pushPath, "/") {
d.md.pushPath = defaultPushPath
}
d.md.pullPath = mdata.GetString(md, pullPath)
if !strings.HasPrefix(d.md.pullPath, "/") {
d.md.pullPath = defaultPullPath
}
d.md.host = mdata.GetString(md, host)
return
}

View File

@ -1,42 +0,0 @@
package quic
import (
"context"
"net"
"github.com/lucas-clemente/quic-go"
)
type quicSession struct {
session quic.Session
}
func (session *quicSession) GetConn() (*quicConn, error) {
stream, err := session.session.OpenStreamSync(context.Background())
if err != nil {
return nil, err
}
return &quicConn{
Stream: stream,
laddr: session.session.LocalAddr(),
raddr: session.session.RemoteAddr(),
}, nil
}
func (session *quicSession) Close() error {
return session.session.CloseWithError(quic.ApplicationErrorCode(0), "closed")
}
type quicConn struct {
quic.Stream
laddr net.Addr
raddr net.Addr
}
func (c *quicConn) LocalAddr() net.Addr {
return c.laddr
}
func (c *quicConn) RemoteAddr() net.Addr {
return c.raddr
}

View File

@ -1,128 +0,0 @@
package quic
import (
"context"
"errors"
"net"
"sync"
"github.com/go-gost/gost/pkg/dialer"
quic_util "github.com/go-gost/gost/pkg/internal/util/quic"
"github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
"github.com/lucas-clemente/quic-go"
)
func init() {
registry.DialerRegistry().Register("quic", NewDialer)
}
type quicDialer struct {
sessions map[string]*quicSession
sessionMutex 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 &quicDialer{
sessions: make(map[string]*quicSession),
logger: options.Logger,
options: options,
}
}
func (d *quicDialer) Init(md md.Metadata) (err error) {
if err = d.parseMetadata(md); err != nil {
return
}
return nil
}
func (d *quicDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (conn net.Conn, err error) {
if _, _, err := net.SplitHostPort(addr); err != nil {
addr = net.JoinHostPort(addr, "0")
}
udpAddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil {
return nil, err
}
d.sessionMutex.Lock()
defer d.sessionMutex.Unlock()
session, ok := d.sessions[addr]
if !ok {
options := &dialer.DialOptions{}
for _, opt := range opts {
opt(options)
}
c, err := options.NetDialer.Dial(ctx, "udp", "")
if err != nil {
return nil, err
}
pc, ok := c.(net.PacketConn)
if !ok {
c.Close()
return nil, errors.New("quic: wrong connection type")
}
if d.md.cipherKey != nil {
pc = quic_util.CipherPacketConn(pc, d.md.cipherKey)
}
session, err = d.initSession(ctx, udpAddr, pc)
if err != nil {
d.logger.Error(err)
pc.Close()
return nil, err
}
d.sessions[addr] = session
}
conn, err = session.GetConn()
if err != nil {
session.Close()
delete(d.sessions, addr)
return nil, err
}
return
}
func (d *quicDialer) initSession(ctx context.Context, addr net.Addr, conn net.PacketConn) (*quicSession, error) {
quicConfig := &quic.Config{
KeepAlive: d.md.keepAlive,
HandshakeIdleTimeout: d.md.handshakeTimeout,
MaxIdleTimeout: d.md.maxIdleTimeout,
Versions: []quic.VersionNumber{
quic.Version1,
quic.VersionDraft29,
},
}
tlsCfg := d.options.TLSConfig
tlsCfg.NextProtos = []string{"http/3", "quic/v1"}
session, err := quic.DialContext(ctx, conn, addr, addr.String(), tlsCfg, quicConfig)
if err != nil {
return nil, err
}
return &quicSession{session: session}, nil
}
// Multiplex implements dialer.Multiplexer interface.
func (d *quicDialer) Multiplex() bool {
return true
}

View File

@ -1,40 +0,0 @@
package quic
import (
"time"
mdata "github.com/go-gost/gost/pkg/metadata"
)
type metadata struct {
keepAlive bool
maxIdleTimeout time.Duration
handshakeTimeout time.Duration
cipherKey []byte
host string
}
func (d *quicDialer) parseMetadata(md mdata.Metadata) (err error) {
const (
keepAlive = "keepAlive"
handshakeTimeout = "handshakeTimeout"
maxIdleTimeout = "maxIdleTimeout"
cipherKey = "cipherKey"
host = "host"
)
d.md.handshakeTimeout = mdata.GetDuration(md, handshakeTimeout)
if key := mdata.GetString(md, cipherKey); key != "" {
d.md.cipherKey = []byte(key)
}
d.md.keepAlive = mdata.GetBool(md, keepAlive)
d.md.handshakeTimeout = mdata.GetDuration(md, handshakeTimeout)
d.md.maxIdleTimeout = mdata.GetDuration(md, maxIdleTimeout)
d.md.host = mdata.GetString(md, host)
return
}

View File

@ -1,31 +0,0 @@
package ssh
import (
"net"
"golang.org/x/crypto/ssh"
)
type sshSession struct {
addr string
conn net.Conn
client *ssh.Client
closed chan struct{}
dead chan struct{}
}
func (s *sshSession) IsClosed() bool {
select {
case <-s.dead:
return true
case <-s.closed:
return true
default:
}
return false
}
func (s *sshSession) wait() error {
defer close(s.closed)
return s.client.Wait()
}

View File

@ -1,165 +0,0 @@
package ssh
import (
"context"
"errors"
"net"
"sync"
"time"
"github.com/go-gost/gost/pkg/dialer"
ssh_util "github.com/go-gost/gost/pkg/internal/util/ssh"
"github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
"golang.org/x/crypto/ssh"
)
func init() {
registry.DialerRegistry().Register("ssh", NewDialer)
}
type sshDialer struct {
sessions map[string]*sshSession
sessionMutex sync.Mutex
logger logger.Logger
md metadata
}
func NewDialer(opts ...dialer.Option) dialer.Dialer {
options := &dialer.Options{}
for _, opt := range opts {
opt(options)
}
return &sshDialer{
sessions: make(map[string]*sshSession),
logger: options.Logger,
}
}
func (d *sshDialer) Init(md md.Metadata) (err error) {
if err = d.parseMetadata(md); err != nil {
return
}
return nil
}
// Multiplex implements dialer.Multiplexer interface.
func (d *sshDialer) Multiplex() bool {
return true
}
func (d *sshDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (conn net.Conn, err error) {
d.sessionMutex.Lock()
defer d.sessionMutex.Unlock()
session, ok := d.sessions[addr]
if session != nil && session.IsClosed() {
delete(d.sessions, addr) // session is dead
ok = false
}
if !ok {
var options dialer.DialOptions
for _, opt := range opts {
opt(&options)
}
conn, err = options.NetDialer.Dial(ctx, "tcp", addr)
if err != nil {
return
}
session = &sshSession{
addr: addr,
conn: conn,
}
d.sessions[addr] = session
}
return session.conn, err
}
// Handshake implements dialer.Handshaker
func (d *sshDialer) Handshake(ctx context.Context, conn net.Conn, options ...dialer.HandshakeOption) (net.Conn, error) {
opts := &dialer.HandshakeOptions{}
for _, option := range options {
option(opts)
}
d.sessionMutex.Lock()
defer d.sessionMutex.Unlock()
if d.md.handshakeTimeout > 0 {
conn.SetDeadline(time.Now().Add(d.md.handshakeTimeout))
defer conn.SetDeadline(time.Time{})
}
session, ok := d.sessions[opts.Addr]
if session != nil && session.conn != conn {
err := errors.New("ssh: unrecognized connection")
d.logger.Error(err)
conn.Close()
delete(d.sessions, opts.Addr)
return nil, err
}
if !ok || session.client == nil {
s, err := d.initSession(ctx, opts.Addr, conn)
if err != nil {
d.logger.Error(err)
conn.Close()
delete(d.sessions, opts.Addr)
return nil, err
}
session = s
go func() {
s.wait()
d.logger.Debug("session closed")
}()
d.sessions[opts.Addr] = session
}
if session.IsClosed() {
delete(d.sessions, opts.Addr)
return nil, ssh_util.ErrSessionDead
}
channel, reqs, err := session.client.OpenChannel(ssh_util.GostSSHTunnelRequest, nil)
if err != nil {
return nil, err
}
go ssh.DiscardRequests(reqs)
return ssh_util.NewConn(conn, channel), nil
}
func (d *sshDialer) initSession(ctx context.Context, addr string, conn net.Conn) (*sshSession, error) {
config := ssh.ClientConfig{
Timeout: 30 * time.Second,
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
if d.md.user != nil {
config.User = d.md.user.Username()
if password, _ := d.md.user.Password(); password != "" {
config.Auth = []ssh.AuthMethod{
ssh.Password(password),
}
}
}
if d.md.signer != nil {
config.Auth = append(config.Auth, ssh.PublicKeys(d.md.signer))
}
sshConn, chans, reqs, err := ssh.NewClientConn(conn, addr, &config)
if err != nil {
return nil, err
}
return &sshSession{
conn: conn,
client: ssh.NewClient(sshConn, chans, reqs),
closed: make(chan struct{}),
dead: make(chan struct{}),
}, nil
}

View File

@ -1,56 +0,0 @@
package ssh
import (
"io/ioutil"
"net/url"
"strings"
"time"
mdata "github.com/go-gost/gost/pkg/metadata"
"golang.org/x/crypto/ssh"
)
type metadata struct {
handshakeTimeout time.Duration
user *url.Userinfo
signer ssh.Signer
}
func (d *sshDialer) parseMetadata(md mdata.Metadata) (err error) {
const (
handshakeTimeout = "handshakeTimeout"
user = "user"
privateKeyFile = "privateKeyFile"
passphrase = "passphrase"
)
if v := mdata.GetString(md, user); v != "" {
ss := strings.SplitN(v, ":", 2)
if len(ss) == 1 {
d.md.user = url.User(ss[0])
} else {
d.md.user = url.UserPassword(ss[0], ss[1])
}
}
if key := mdata.GetString(md, privateKeyFile); key != "" {
data, err := ioutil.ReadFile(key)
if err != nil {
return err
}
pp := mdata.GetString(md, passphrase)
if pp == "" {
d.md.signer, err = ssh.ParsePrivateKey(data)
} else {
d.md.signer, err = ssh.ParsePrivateKeyWithPassphrase(data, []byte(pp))
}
if err != nil {
return err
}
}
d.md.handshakeTimeout = mdata.GetDuration(md, handshakeTimeout)
return
}

View File

@ -1,31 +0,0 @@
package sshd
import (
"net"
"golang.org/x/crypto/ssh"
)
type sshSession struct {
addr string
conn net.Conn
client *ssh.Client
closed chan struct{}
dead chan struct{}
}
func (s *sshSession) IsClosed() bool {
select {
case <-s.dead:
return true
case <-s.closed:
return true
default:
}
return false
}
func (s *sshSession) wait() error {
defer close(s.closed)
return s.client.Wait()
}

Some files were not shown because too many files have changed in this diff Show More