add chain
This commit is contained in:
11
pkg/components/connector/connector.go
Normal file
11
pkg/components/connector/connector.go
Normal file
@ -0,0 +1,11 @@
|
||||
package connector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
)
|
||||
|
||||
// Connector is responsible for connecting to the destination address.
|
||||
type Connector interface {
|
||||
Connect(ctx context.Context, conn net.Conn, network, address string, opts ...ConnectOption) (net.Conn, error)
|
||||
}
|
99
pkg/components/connector/http/connector.go
Normal file
99
pkg/components/connector/http/connector.go
Normal file
@ -0,0 +1,99 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/go-gost/gost/pkg/components/connector"
|
||||
"github.com/go-gost/gost/pkg/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
_ connector.Connector = (*Connector)(nil)
|
||||
)
|
||||
|
||||
type Connector struct {
|
||||
md metadata
|
||||
logger logger.Logger
|
||||
}
|
||||
|
||||
func NewConnector(opts ...connector.Option) *Connector {
|
||||
options := &connector.Options{}
|
||||
for _, opt := range opts {
|
||||
opt(options)
|
||||
}
|
||||
|
||||
return &Connector{
|
||||
logger: options.Logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Connector) Init(md connector.Metadata) (err error) {
|
||||
c.md, err = c.parseMetadata(md)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Connector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
|
||||
req := &http.Request{
|
||||
Method: http.MethodConnect,
|
||||
URL: &url.URL{Host: address},
|
||||
Host: address,
|
||||
ProtoMajor: 1,
|
||||
ProtoMinor: 1,
|
||||
Header: make(http.Header),
|
||||
}
|
||||
if c.md.UserAgent != "" {
|
||||
log.Println(c.md.UserAgent)
|
||||
req.Header.Set("User-Agent", c.md.UserAgent)
|
||||
}
|
||||
req.Header.Set("Proxy-Connection", "keep-alive")
|
||||
|
||||
if user := c.md.User; user != nil {
|
||||
u := user.Username()
|
||||
p, _ := user.Password()
|
||||
req.Header.Set("Proxy-Authorization",
|
||||
"Basic "+base64.StdEncoding.EncodeToString([]byte(u+":"+p)))
|
||||
}
|
||||
|
||||
req = req.WithContext(ctx)
|
||||
if err := req.Write(conn); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := http.ReadResponse(bufio.NewReader(conn), req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("%s", resp.Status)
|
||||
}
|
||||
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func (c *Connector) parseMetadata(md connector.Metadata) (m metadata, err error) {
|
||||
if md == nil {
|
||||
md = connector.Metadata{}
|
||||
}
|
||||
m.UserAgent = md[userAgent]
|
||||
if m.UserAgent == "" {
|
||||
m.UserAgent = defaultUserAgent
|
||||
}
|
||||
|
||||
if v, ok := md[username]; ok {
|
||||
m.User = url.UserPassword(v, md[password])
|
||||
}
|
||||
|
||||
return
|
||||
}
|
18
pkg/components/connector/http/metadata.go
Normal file
18
pkg/components/connector/http/metadata.go
Normal file
@ -0,0 +1,18 @@
|
||||
package http
|
||||
|
||||
import "net/url"
|
||||
|
||||
const (
|
||||
userAgent = "userAgent"
|
||||
username = "username"
|
||||
password = "password"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultUserAgent = "Chrome/78.0.3904.106"
|
||||
)
|
||||
|
||||
type metadata struct {
|
||||
UserAgent string
|
||||
User *url.Userinfo
|
||||
}
|
3
pkg/components/connector/metadata.go
Normal file
3
pkg/components/connector/metadata.go
Normal file
@ -0,0 +1,3 @@
|
||||
package connector
|
||||
|
||||
type Metadata map[string]string
|
22
pkg/components/connector/option.go
Normal file
22
pkg/components/connector/option.go
Normal file
@ -0,0 +1,22 @@
|
||||
package connector
|
||||
|
||||
import (
|
||||
"github.com/go-gost/gost/pkg/logger"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
Logger logger.Logger
|
||||
}
|
||||
|
||||
type Option func(opts *Options)
|
||||
|
||||
func LoggerOption(logger logger.Logger) Option {
|
||||
return func(opts *Options) {
|
||||
opts.Logger = logger
|
||||
}
|
||||
}
|
||||
|
||||
type ConnectOptions struct {
|
||||
}
|
||||
|
||||
type ConnectOption func(opts *ConnectOptions)
|
54
pkg/components/connector/ss/connector.go
Normal file
54
pkg/components/connector/ss/connector.go
Normal file
@ -0,0 +1,54 @@
|
||||
package ss
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/go-gost/gost/pkg/components/connector"
|
||||
"github.com/go-gost/gost/pkg/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
_ connector.Connector = (*Connector)(nil)
|
||||
)
|
||||
|
||||
type Connector struct {
|
||||
md metadata
|
||||
logger logger.Logger
|
||||
}
|
||||
|
||||
func NewConnector(opts ...connector.Option) *Connector {
|
||||
options := &connector.Options{}
|
||||
for _, opt := range opts {
|
||||
opt(options)
|
||||
}
|
||||
|
||||
return &Connector{
|
||||
logger: options.Logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Connector) Init(md connector.Metadata) (err error) {
|
||||
c.md, err = c.parseMetadata(md)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Connector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
|
||||
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func (c *Connector) parseMetadata(md connector.Metadata) (m metadata, err error) {
|
||||
if md == nil {
|
||||
md = connector.Metadata{}
|
||||
}
|
||||
|
||||
m.method = md[method]
|
||||
m.password = md[password]
|
||||
|
||||
return
|
||||
}
|
11
pkg/components/connector/ss/metadata.go
Normal file
11
pkg/components/connector/ss/metadata.go
Normal file
@ -0,0 +1,11 @@
|
||||
package ss
|
||||
|
||||
const (
|
||||
method = "method"
|
||||
password = "password"
|
||||
)
|
||||
|
||||
type metadata struct {
|
||||
method string
|
||||
password string
|
||||
}
|
Reference in New Issue
Block a user