update config
This commit is contained in:
167
cmd/gost/cmd.go
167
cmd/gost/cmd.go
@ -7,10 +7,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/config"
|
"github.com/go-gost/gost/pkg/config"
|
||||||
|
"github.com/go-gost/gost/pkg/registry"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrInvalidService = errors.New("invalid service")
|
ErrInvalidCmd = errors.New("invalid cmd")
|
||||||
ErrInvalidNode = errors.New("invalid node")
|
ErrInvalidNode = errors.New("invalid node")
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -36,32 +37,36 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, node := range nodes {
|
for i, node := range nodes {
|
||||||
url, err := checkCmd(node)
|
url, err := normCmd(node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nodeConfig, err := buildNodeConfig(url)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
nodeConfig.Name = "node-0"
|
||||||
|
|
||||||
chain.Hops = append(chain.Hops, &config.HopConfig{
|
chain.Hops = append(chain.Hops, &config.HopConfig{
|
||||||
Name: fmt.Sprintf("hop-%d", i),
|
Name: fmt.Sprintf("hop-%d", i),
|
||||||
Nodes: []*config.NodeConfig{
|
Nodes: []*config.NodeConfig{nodeConfig},
|
||||||
{
|
|
||||||
Name: "node-0",
|
|
||||||
URL: url,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, svc := range services {
|
for i, svc := range services {
|
||||||
url, err := checkCmd(svc)
|
url, err := normCmd(svc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
service := &config.ServiceConfig{
|
|
||||||
Name: fmt.Sprintf("service-%d", i),
|
service, err := buildServiceConfig(url)
|
||||||
URL: url,
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
service.Name = fmt.Sprintf("service-%d", i)
|
||||||
if chain != nil {
|
if chain != nil {
|
||||||
service.Chain = chain.Name
|
service.Handler.Chain = chain.Name
|
||||||
}
|
}
|
||||||
cfg.Services = append(cfg.Services, service)
|
cfg.Services = append(cfg.Services, service)
|
||||||
}
|
}
|
||||||
@ -69,20 +74,140 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
|
|||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkCmd(s string) (string, error) {
|
func buildServiceConfig(url *url.URL) (*config.ServiceConfig, error) {
|
||||||
|
var handler, listener string
|
||||||
|
schemes := strings.Split(url.Scheme, "+")
|
||||||
|
if len(schemes) == 1 {
|
||||||
|
handler = schemes[0]
|
||||||
|
listener = schemes[0]
|
||||||
|
}
|
||||||
|
if len(schemes) == 2 {
|
||||||
|
handler = schemes[0]
|
||||||
|
listener = schemes[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
svc := &config.ServiceConfig{
|
||||||
|
Addr: url.Host,
|
||||||
|
}
|
||||||
|
|
||||||
|
if h := registry.GetHandler(handler); h == nil {
|
||||||
|
handler = "auto"
|
||||||
|
}
|
||||||
|
if ln := registry.GetListener(listener); ln == nil {
|
||||||
|
listener = "tcp"
|
||||||
|
if handler == "ssu" {
|
||||||
|
listener = "udp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if remotes := strings.Trim(url.EscapedPath(), "/"); remotes != "" {
|
||||||
|
svc.Forwarder = &config.ForwarderConfig{
|
||||||
|
Targets: strings.Split(remotes, ","),
|
||||||
|
}
|
||||||
|
if handler != "relay" {
|
||||||
|
if listener == "tcp" || listener == "udp" ||
|
||||||
|
listener == "rtcp" || listener == "rudp" ||
|
||||||
|
listener == "tun" || listener == "tap" {
|
||||||
|
handler = listener
|
||||||
|
} else {
|
||||||
|
handler = "tcp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
md := make(map[string]interface{})
|
||||||
|
for k, v := range url.Query() {
|
||||||
|
if len(v) > 0 {
|
||||||
|
md[k] = v[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var auths []config.AuthConfig
|
||||||
|
if url.User != nil {
|
||||||
|
auth := config.AuthConfig{
|
||||||
|
Username: url.User.Username(),
|
||||||
|
}
|
||||||
|
auth.Password, _ = url.User.Password()
|
||||||
|
auths = append(auths, auth)
|
||||||
|
}
|
||||||
|
|
||||||
|
svc.Handler = &config.HandlerConfig{
|
||||||
|
Type: handler,
|
||||||
|
Auths: auths,
|
||||||
|
Metadata: md,
|
||||||
|
}
|
||||||
|
svc.Listener = &config.ListenerConfig{
|
||||||
|
Type: listener,
|
||||||
|
Metadata: md,
|
||||||
|
}
|
||||||
|
|
||||||
|
return svc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildNodeConfig(url *url.URL) (*config.NodeConfig, error) {
|
||||||
|
var connector, dialer string
|
||||||
|
schemes := strings.Split(url.Scheme, "+")
|
||||||
|
if len(schemes) == 1 {
|
||||||
|
connector = schemes[0]
|
||||||
|
dialer = schemes[0]
|
||||||
|
}
|
||||||
|
if len(schemes) == 2 {
|
||||||
|
connector = schemes[0]
|
||||||
|
dialer = schemes[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
node := &config.NodeConfig{
|
||||||
|
Addr: url.Host,
|
||||||
|
}
|
||||||
|
|
||||||
|
if c := registry.GetConnector(connector); c == nil {
|
||||||
|
connector = "http"
|
||||||
|
}
|
||||||
|
if d := registry.GetDialer(dialer); d == nil {
|
||||||
|
dialer = "tcp"
|
||||||
|
if connector == "ssu" {
|
||||||
|
dialer = "udp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
md := make(map[string]interface{})
|
||||||
|
for k, v := range url.Query() {
|
||||||
|
if len(v) > 0 {
|
||||||
|
md[k] = v[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
md["serverName"] = url.Host
|
||||||
|
|
||||||
|
var auth *config.AuthConfig
|
||||||
|
if url.User != nil {
|
||||||
|
auth = &config.AuthConfig{
|
||||||
|
Username: url.User.Username(),
|
||||||
|
}
|
||||||
|
auth.Password, _ = url.User.Password()
|
||||||
|
}
|
||||||
|
|
||||||
|
node.Connector = &config.ConnectorConfig{
|
||||||
|
Type: connector,
|
||||||
|
Auth: auth,
|
||||||
|
Metadata: md,
|
||||||
|
}
|
||||||
|
node.Dialer = &config.DialerConfig{
|
||||||
|
Type: dialer,
|
||||||
|
Metadata: md,
|
||||||
|
}
|
||||||
|
|
||||||
|
return node, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func normCmd(s string) (*url.URL, error) {
|
||||||
s = strings.TrimSpace(s)
|
s = strings.TrimSpace(s)
|
||||||
if s == "" {
|
if s == "" {
|
||||||
return "", ErrInvalidService
|
return nil, ErrInvalidCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.Contains(s, "://") {
|
if !strings.Contains(s, "://") {
|
||||||
s = "auto://" + s
|
s = "auto://" + s
|
||||||
}
|
}
|
||||||
|
|
||||||
u, err := url.Parse(s)
|
return url.Parse(s)
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return u.String(), nil
|
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,11 @@ package main
|
|||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-gost/gost/pkg/auth"
|
||||||
"github.com/go-gost/gost/pkg/bypass"
|
"github.com/go-gost/gost/pkg/bypass"
|
||||||
"github.com/go-gost/gost/pkg/chain"
|
"github.com/go-gost/gost/pkg/chain"
|
||||||
"github.com/go-gost/gost/pkg/config"
|
"github.com/go-gost/gost/pkg/config"
|
||||||
@ -54,12 +56,14 @@ func buildService(cfg *config.Config) (services []*service.Service) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, svc := range cfg.Services {
|
for _, svc := range cfg.Services {
|
||||||
|
if svc.Listener == nil || svc.Handler == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
serviceLogger := log.WithFields(map[string]interface{}{
|
serviceLogger := log.WithFields(map[string]interface{}{
|
||||||
"kind": "service",
|
"kind": "service",
|
||||||
"service": svc.Name,
|
"service": svc.Name,
|
||||||
"listener": svc.Listener.Type,
|
"listener": svc.Listener.Type,
|
||||||
"handler": svc.Handler.Type,
|
"handler": svc.Handler.Type,
|
||||||
"chain": svc.Chain,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
listenerLogger := serviceLogger.WithFields(map[string]interface{}{
|
listenerLogger := serviceLogger.WithFields(map[string]interface{}{
|
||||||
@ -67,11 +71,12 @@ func buildService(cfg *config.Config) (services []*service.Service) {
|
|||||||
})
|
})
|
||||||
ln := registry.GetListener(svc.Listener.Type)(
|
ln := registry.GetListener(svc.Listener.Type)(
|
||||||
listener.AddrOption(svc.Addr),
|
listener.AddrOption(svc.Addr),
|
||||||
|
listener.AuthenticatorOption(authFromConfig(svc.Listener.Auths...)),
|
||||||
listener.LoggerOption(listenerLogger),
|
listener.LoggerOption(listenerLogger),
|
||||||
)
|
)
|
||||||
|
|
||||||
if chainable, ok := ln.(chain.Chainable); ok {
|
if chainable, ok := ln.(chain.Chainable); ok {
|
||||||
chainable.WithChain(chains[svc.Chain])
|
chainable.WithChain(chains[svc.Listener.Chain])
|
||||||
}
|
}
|
||||||
|
|
||||||
if svc.Listener.Metadata == nil {
|
if svc.Listener.Metadata == nil {
|
||||||
@ -86,12 +91,13 @@ func buildService(cfg *config.Config) (services []*service.Service) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
h := registry.GetHandler(svc.Handler.Type)(
|
h := registry.GetHandler(svc.Handler.Type)(
|
||||||
handler.BypassOption(bypasses[svc.Bypass]),
|
|
||||||
handler.LoggerOption(handlerLogger),
|
handler.LoggerOption(handlerLogger),
|
||||||
|
handler.BypassOption(bypasses[svc.Handler.Bypass]),
|
||||||
|
handler.AuthenticatorOption(authFromConfig(svc.Handler.Auths...)),
|
||||||
handler.RouterOption(&chain.Router{
|
handler.RouterOption(&chain.Router{
|
||||||
Chain: chains[svc.Chain],
|
Chain: chains[svc.Handler.Chain],
|
||||||
Resolver: resolvers[svc.Resolver],
|
Resolver: resolvers[svc.Handler.Resolver],
|
||||||
Hosts: hosts[svc.Hosts],
|
Hosts: hosts[svc.Handler.Hosts],
|
||||||
Logger: handlerLogger,
|
Logger: handlerLogger,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
@ -134,14 +140,27 @@ func chainFromConfig(cfg *config.ChainConfig) *chain.Chain {
|
|||||||
for _, hop := range cfg.Hops {
|
for _, hop := range cfg.Hops {
|
||||||
group := &chain.NodeGroup{}
|
group := &chain.NodeGroup{}
|
||||||
for _, v := range hop.Nodes {
|
for _, v := range hop.Nodes {
|
||||||
connectorLogger := chainLogger.WithFields(map[string]interface{}{
|
nodeLogger := chainLogger.WithFields(map[string]interface{}{
|
||||||
"kind": "connector",
|
"kind": "node",
|
||||||
"connector": v.Connector.Type,
|
"connector": v.Connector.Type,
|
||||||
"dialer": v.Dialer.Type,
|
"dialer": v.Dialer.Type,
|
||||||
"hop": hop.Name,
|
"hop": hop.Name,
|
||||||
"node": v.Name,
|
"node": v.Name,
|
||||||
})
|
})
|
||||||
|
connectorLogger := nodeLogger.WithFields(map[string]interface{}{
|
||||||
|
"kind": "connector",
|
||||||
|
})
|
||||||
|
|
||||||
|
var connectorUser *url.Userinfo
|
||||||
|
if auth := v.Connector.Auth; auth != nil && auth.Username != "" {
|
||||||
|
if auth.Password == "" {
|
||||||
|
connectorUser = url.User(auth.Username)
|
||||||
|
} else {
|
||||||
|
connectorUser = url.UserPassword(auth.Username, auth.Password)
|
||||||
|
}
|
||||||
|
}
|
||||||
cr := registry.GetConnector(v.Connector.Type)(
|
cr := registry.GetConnector(v.Connector.Type)(
|
||||||
|
connector.UserOption(connectorUser),
|
||||||
connector.LoggerOption(connectorLogger),
|
connector.LoggerOption(connectorLogger),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -152,14 +171,20 @@ func chainFromConfig(cfg *config.ChainConfig) *chain.Chain {
|
|||||||
connectorLogger.Fatal("init: ", err)
|
connectorLogger.Fatal("init: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dialerLogger := chainLogger.WithFields(map[string]interface{}{
|
dialerLogger := nodeLogger.WithFields(map[string]interface{}{
|
||||||
"kind": "dialer",
|
"kind": "dialer",
|
||||||
"connector": v.Connector.Type,
|
|
||||||
"dialer": v.Dialer.Type,
|
|
||||||
"hop": hop.Name,
|
|
||||||
"node": v.Name,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
var dialerUser *url.Userinfo
|
||||||
|
if auth := v.Dialer.Auth; auth != nil && auth.Username != "" {
|
||||||
|
if auth.Password == "" {
|
||||||
|
dialerUser = url.User(auth.Username)
|
||||||
|
} else {
|
||||||
|
dialerUser = url.UserPassword(auth.Username, auth.Password)
|
||||||
|
}
|
||||||
|
}
|
||||||
d := registry.GetDialer(v.Dialer.Type)(
|
d := registry.GetDialer(v.Dialer.Type)(
|
||||||
|
dialer.UserOption(dialerUser),
|
||||||
dialer.LoggerOption(dialerLogger),
|
dialer.LoggerOption(dialerLogger),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -305,3 +330,18 @@ func hostsFromConfig(cfg *config.HostsConfig) hostspkg.HostMapper {
|
|||||||
}
|
}
|
||||||
return hosts
|
return hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func authFromConfig(cfgs ...config.AuthConfig) auth.Authenticator {
|
||||||
|
auths := make(map[string]string)
|
||||||
|
for _, cfg := range cfgs {
|
||||||
|
if cfg.Username == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
auths[cfg.Username] = cfg.Password
|
||||||
|
}
|
||||||
|
if len(auths) > 0 {
|
||||||
|
return auth.NewMapAuthenticator(auths)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -63,8 +63,6 @@ func main() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
normConfig(cfg)
|
|
||||||
|
|
||||||
log = logFromConfig(cfg.Log)
|
log = logFromConfig(cfg.Log)
|
||||||
|
|
||||||
if outputCfgFile != "" {
|
if outputCfgFile != "" {
|
||||||
|
139
cmd/gost/norm.go
139
cmd/gost/norm.go
@ -1,139 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/config"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
)
|
|
||||||
|
|
||||||
// normConfig normalizes the config.
|
|
||||||
func normConfig(cfg *config.Config) {
|
|
||||||
for _, svc := range cfg.Services {
|
|
||||||
normService(svc)
|
|
||||||
}
|
|
||||||
for _, chain := range cfg.Chains {
|
|
||||||
normChain(chain)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func normService(svc *config.ServiceConfig) {
|
|
||||||
if svc.URL == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
u, _ := url.Parse(svc.URL)
|
|
||||||
|
|
||||||
var handler, listener string
|
|
||||||
schemes := strings.Split(u.Scheme, "+")
|
|
||||||
if len(schemes) == 1 {
|
|
||||||
handler = schemes[0]
|
|
||||||
listener = schemes[0]
|
|
||||||
}
|
|
||||||
if len(schemes) == 2 {
|
|
||||||
handler = schemes[0]
|
|
||||||
listener = schemes[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
md := make(map[string]interface{})
|
|
||||||
for k, v := range u.Query() {
|
|
||||||
if len(v) > 0 {
|
|
||||||
md[k] = v[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if u.User != nil {
|
|
||||||
md["users"] = []interface{}{u.User.String()}
|
|
||||||
}
|
|
||||||
|
|
||||||
svc.Addr = u.Host
|
|
||||||
|
|
||||||
if h := registry.GetHandler(handler); h == nil {
|
|
||||||
handler = "auto"
|
|
||||||
}
|
|
||||||
if ln := registry.GetListener(listener); ln == nil {
|
|
||||||
listener = "tcp"
|
|
||||||
if handler == "ssu" {
|
|
||||||
listener = "udp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if remotes := strings.Trim(u.EscapedPath(), "/"); remotes != "" {
|
|
||||||
svc.Forwarder = &config.ForwarderConfig{
|
|
||||||
Targets: strings.Split(remotes, ","),
|
|
||||||
}
|
|
||||||
if handler != "relay" {
|
|
||||||
if listener == "tcp" || listener == "udp" ||
|
|
||||||
listener == "rtcp" || listener == "rudp" ||
|
|
||||||
listener == "tun" || listener == "tap" {
|
|
||||||
handler = listener
|
|
||||||
} else {
|
|
||||||
handler = "tcp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
svc.Handler = &config.HandlerConfig{
|
|
||||||
Type: handler,
|
|
||||||
Metadata: md,
|
|
||||||
}
|
|
||||||
svc.Listener = &config.ListenerConfig{
|
|
||||||
Type: listener,
|
|
||||||
Metadata: md,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func normChain(chain *config.ChainConfig) {
|
|
||||||
for _, hop := range chain.Hops {
|
|
||||||
for _, node := range hop.Nodes {
|
|
||||||
if node.URL == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
u, _ := url.Parse(node.URL)
|
|
||||||
|
|
||||||
var connector, dialer string
|
|
||||||
schemes := strings.Split(u.Scheme, "+")
|
|
||||||
if len(schemes) == 1 {
|
|
||||||
connector = schemes[0]
|
|
||||||
dialer = schemes[0]
|
|
||||||
}
|
|
||||||
if len(schemes) == 2 {
|
|
||||||
connector = schemes[0]
|
|
||||||
dialer = schemes[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
md := make(map[string]interface{})
|
|
||||||
for k, v := range u.Query() {
|
|
||||||
if len(v) > 0 {
|
|
||||||
md[k] = v[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if u.User != nil {
|
|
||||||
md["user"] = u.User.String()
|
|
||||||
}
|
|
||||||
md["serverName"] = u.Host
|
|
||||||
|
|
||||||
node.Addr = u.Host
|
|
||||||
|
|
||||||
if c := registry.GetConnector(connector); c == nil {
|
|
||||||
connector = "http"
|
|
||||||
}
|
|
||||||
if d := registry.GetDialer(dialer); d == nil {
|
|
||||||
dialer = "tcp"
|
|
||||||
if connector == "ssu" {
|
|
||||||
dialer = "udp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
node.Connector = &config.ConnectorConfig{
|
|
||||||
Type: connector,
|
|
||||||
Metadata: md,
|
|
||||||
}
|
|
||||||
node.Dialer = &config.DialerConfig{
|
|
||||||
Type: dialer,
|
|
||||||
Metadata: md,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
30
gost.yml
30
gost.yml
@ -7,13 +7,12 @@ services:
|
|||||||
- name: http+tcp
|
- name: http+tcp
|
||||||
url: "http://gost:gost@:8000"
|
url: "http://gost:gost@:8000"
|
||||||
addr: ":28000"
|
addr: ":28000"
|
||||||
chain: chain01
|
|
||||||
# bypass: bypass01
|
|
||||||
handler:
|
handler:
|
||||||
type: http
|
type: http
|
||||||
|
chain: chain01
|
||||||
|
# bypass: bypass01
|
||||||
metadata:
|
metadata:
|
||||||
proxyAgent: "gost/3.0"
|
proxyAgent: "gost/3.0"
|
||||||
retry: 3
|
|
||||||
auths:
|
auths:
|
||||||
- user1:pass1
|
- user1:pass1
|
||||||
- user2:pass2
|
- user2:pass2
|
||||||
@ -26,10 +25,10 @@ services:
|
|||||||
- name: ss
|
- name: ss
|
||||||
url: "ss://chacha20:gost@:8000"
|
url: "ss://chacha20:gost@:8000"
|
||||||
addr: ":28338"
|
addr: ":28338"
|
||||||
# chain: chain01
|
|
||||||
# bypass: bypass01
|
|
||||||
handler:
|
handler:
|
||||||
type: ss
|
type: ss
|
||||||
|
# chain: chain01
|
||||||
|
# bypass: bypass01
|
||||||
metadata:
|
metadata:
|
||||||
method: chacha20-ietf
|
method: chacha20-ietf
|
||||||
password: gost
|
password: gost
|
||||||
@ -43,10 +42,10 @@ services:
|
|||||||
- name: socks5
|
- name: socks5
|
||||||
url: "socks5://gost:gost@:1080"
|
url: "socks5://gost:gost@:1080"
|
||||||
addr: ":21080"
|
addr: ":21080"
|
||||||
# chain: chain-ss
|
|
||||||
# bypass: bypass01
|
|
||||||
handler:
|
handler:
|
||||||
type: socks5
|
type: socks5
|
||||||
|
# chain: chain-ss
|
||||||
|
# bypass: bypass01
|
||||||
metadata:
|
metadata:
|
||||||
auths:
|
auths:
|
||||||
- gost:gost
|
- gost:gost
|
||||||
@ -112,7 +111,6 @@ services:
|
|||||||
|
|
||||||
- name: rtcp
|
- name: rtcp
|
||||||
addr: ":28100"
|
addr: ":28100"
|
||||||
# chain: chain-socks5
|
|
||||||
forwarder:
|
forwarder:
|
||||||
targets:
|
targets:
|
||||||
- 192.168.8.8:80
|
- 192.168.8.8:80
|
||||||
@ -122,6 +120,7 @@ services:
|
|||||||
readTimeout: 5s
|
readTimeout: 5s
|
||||||
listener:
|
listener:
|
||||||
type: rtcp
|
type: rtcp
|
||||||
|
# chain: chain-socks5
|
||||||
metadata:
|
metadata:
|
||||||
keepAlive: 15s
|
keepAlive: 15s
|
||||||
mux: true
|
mux: true
|
||||||
@ -318,21 +317,6 @@ hosts:
|
|||||||
- bar
|
- bar
|
||||||
- baz
|
- baz
|
||||||
|
|
||||||
probeResistance:
|
|
||||||
- name: pr-code404
|
|
||||||
type: code
|
|
||||||
value: 404
|
|
||||||
knock: www.example.com
|
|
||||||
- name: pr-web
|
|
||||||
type: web
|
|
||||||
value: http://example.com/page.html
|
|
||||||
- name: pr-host
|
|
||||||
type: host
|
|
||||||
value: example.com:80
|
|
||||||
- name: pr-file
|
|
||||||
type: file
|
|
||||||
value: /path/to/file
|
|
||||||
|
|
||||||
profiling:
|
profiling:
|
||||||
addr: ":6060"
|
addr: ":6060"
|
||||||
enabled: true
|
enabled: true
|
||||||
|
@ -6,22 +6,22 @@ type Authenticator interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LocalAuthenticator is an Authenticator that authenticates client by local key-value pairs.
|
// LocalAuthenticator is an Authenticator that authenticates client by local key-value pairs.
|
||||||
type LocalAuthenticator struct {
|
type MapAuthenticator struct {
|
||||||
kvs map[string]string
|
kvs map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLocalAuthenticator creates an Authenticator that authenticates client by local infos.
|
// NewMapAuthenticator creates an Authenticator that authenticates client by local infos.
|
||||||
func NewLocalAuthenticator(kvs map[string]string) *LocalAuthenticator {
|
func NewMapAuthenticator(kvs map[string]string) *MapAuthenticator {
|
||||||
if kvs == nil {
|
if kvs == nil {
|
||||||
kvs = make(map[string]string)
|
kvs = make(map[string]string)
|
||||||
}
|
}
|
||||||
return &LocalAuthenticator{
|
return &MapAuthenticator{
|
||||||
kvs: kvs,
|
kvs: kvs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Authenticate checks the validity of the provided user-password pair.
|
// Authenticate checks the validity of the provided user-password pair.
|
||||||
func (au *LocalAuthenticator) Authenticate(user, password string) bool {
|
func (au *MapAuthenticator) Authenticate(user, password string) bool {
|
||||||
if au == nil {
|
if au == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -33,8 +33,3 @@ func (au *LocalAuthenticator) Authenticate(user, password string) bool {
|
|||||||
v, ok := au.kvs[user]
|
v, ok := au.kvs[user]
|
||||||
return ok && (v == "" || password == v)
|
return ok && (v == "" || password == v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add adds a key-value pair to the Authenticator.
|
|
||||||
func (au *LocalAuthenticator) Add(k, v string) {
|
|
||||||
au.kvs[k] = v
|
|
||||||
}
|
|
||||||
|
@ -36,6 +36,11 @@ type TLSConfig struct {
|
|||||||
CA string
|
CA string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AuthConfig struct {
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
|
||||||
type SelectorConfig struct {
|
type SelectorConfig struct {
|
||||||
Strategy string
|
Strategy string
|
||||||
MaxFails int
|
MaxFails int
|
||||||
@ -76,11 +81,18 @@ type HostsConfig struct {
|
|||||||
|
|
||||||
type ListenerConfig struct {
|
type ListenerConfig struct {
|
||||||
Type string
|
Type string
|
||||||
|
Chain string `yaml:",omitempty"`
|
||||||
|
Auths []AuthConfig `yaml:",omitempty"`
|
||||||
Metadata map[string]interface{} `yaml:",omitempty"`
|
Metadata map[string]interface{} `yaml:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type HandlerConfig struct {
|
type HandlerConfig struct {
|
||||||
Type string
|
Type string
|
||||||
|
Chain string `yaml:",omitempty"`
|
||||||
|
Bypass string `yaml:",omitempty"`
|
||||||
|
Resolver string `yaml:",omitempty"`
|
||||||
|
Hosts string `yaml:",omitempty"`
|
||||||
|
Auths []AuthConfig `yaml:",omitempty"`
|
||||||
Metadata map[string]interface{} `yaml:",omitempty"`
|
Metadata map[string]interface{} `yaml:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,24 +103,21 @@ type ForwarderConfig struct {
|
|||||||
|
|
||||||
type DialerConfig struct {
|
type DialerConfig struct {
|
||||||
Type string
|
Type string
|
||||||
|
Auth *AuthConfig `yaml:",omitempty"`
|
||||||
Metadata map[string]interface{} `yaml:",omitempty"`
|
Metadata map[string]interface{} `yaml:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConnectorConfig struct {
|
type ConnectorConfig struct {
|
||||||
Type string
|
Type string
|
||||||
|
Auth *AuthConfig `yaml:",omitempty"`
|
||||||
Metadata map[string]interface{} `yaml:",omitempty"`
|
Metadata map[string]interface{} `yaml:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServiceConfig struct {
|
type ServiceConfig struct {
|
||||||
Name string
|
Name string
|
||||||
URL string `yaml:",omitempty"`
|
|
||||||
Addr string `yaml:",omitempty"`
|
Addr string `yaml:",omitempty"`
|
||||||
Chain string `yaml:",omitempty"`
|
|
||||||
Bypass string `yaml:",omitempty"`
|
|
||||||
Resolver string `yaml:",omitempty"`
|
|
||||||
Hosts string `yaml:",omitempty"`
|
|
||||||
Listener *ListenerConfig `yaml:",omitempty"`
|
|
||||||
Handler *HandlerConfig `yaml:",omitempty"`
|
Handler *HandlerConfig `yaml:",omitempty"`
|
||||||
|
Listener *ListenerConfig `yaml:",omitempty"`
|
||||||
Forwarder *ForwarderConfig `yaml:",omitempty"`
|
Forwarder *ForwarderConfig `yaml:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +135,6 @@ type HopConfig struct {
|
|||||||
|
|
||||||
type NodeConfig struct {
|
type NodeConfig struct {
|
||||||
Name string
|
Name string
|
||||||
URL string `yaml:",omitempty"`
|
|
||||||
Addr string `yaml:",omitempty"`
|
Addr string `yaml:",omitempty"`
|
||||||
Dialer *DialerConfig `yaml:",omitempty"`
|
Dialer *DialerConfig `yaml:",omitempty"`
|
||||||
Connector *ConnectorConfig `yaml:",omitempty"`
|
Connector *ConnectorConfig `yaml:",omitempty"`
|
||||||
@ -134,14 +142,14 @@ type NodeConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Log *LogConfig `yaml:",omitempty"`
|
Services []*ServiceConfig
|
||||||
Profiling *ProfilingConfig `yaml:",omitempty"`
|
Chains []*ChainConfig `yaml:",omitempty"`
|
||||||
TLS *TLSConfig `yaml:",omitempty"`
|
|
||||||
Bypasses []*BypassConfig `yaml:",omitempty"`
|
Bypasses []*BypassConfig `yaml:",omitempty"`
|
||||||
Resolvers []*ResolverConfig `yaml:",omitempty"`
|
Resolvers []*ResolverConfig `yaml:",omitempty"`
|
||||||
Hosts []*HostsConfig `yaml:",omitempty"`
|
Hosts []*HostsConfig `yaml:",omitempty"`
|
||||||
Chains []*ChainConfig `yaml:",omitempty"`
|
TLS *TLSConfig `yaml:",omitempty"`
|
||||||
Services []*ServiceConfig
|
Log *LogConfig `yaml:",omitempty"`
|
||||||
|
Profiling *ProfilingConfig `yaml:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Load() error {
|
func (c *Config) Load() error {
|
||||||
|
@ -23,6 +23,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type httpConnector struct {
|
type httpConnector struct {
|
||||||
|
user *url.Userinfo
|
||||||
md metadata
|
md metadata
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
}
|
}
|
||||||
@ -34,6 +35,7 @@ func NewConnector(opts ...connector.Option) connector.Connector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &httpConnector{
|
return &httpConnector{
|
||||||
|
user: options.User,
|
||||||
logger: options.Logger,
|
logger: options.Logger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,7 +67,7 @@ func (c *httpConnector) Connect(ctx context.Context, conn net.Conn, network, add
|
|||||||
}
|
}
|
||||||
req.Header.Set("Proxy-Connection", "keep-alive")
|
req.Header.Set("Proxy-Connection", "keep-alive")
|
||||||
|
|
||||||
if user := c.md.User; user != nil {
|
if user := c.user; user != nil {
|
||||||
u := user.Username()
|
u := user.Username()
|
||||||
p, _ := user.Password()
|
p, _ := user.Password()
|
||||||
req.Header.Set("Proxy-Authorization",
|
req.Header.Set("Proxy-Authorization",
|
||||||
|
@ -2,8 +2,6 @@ package http
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
mdata "github.com/go-gost/gost/pkg/metadata"
|
||||||
@ -11,7 +9,6 @@ import (
|
|||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
connectTimeout time.Duration
|
connectTimeout time.Duration
|
||||||
User *url.Userinfo
|
|
||||||
header http.Header
|
header http.Header
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,15 +21,6 @@ func (c *httpConnector) parseMetadata(md mdata.Metadata) (err error) {
|
|||||||
|
|
||||||
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
||||||
|
|
||||||
if v := mdata.GetString(md, user); v != "" {
|
|
||||||
ss := strings.SplitN(v, ":", 2)
|
|
||||||
if len(ss) == 1 {
|
|
||||||
c.md.User = url.User(ss[0])
|
|
||||||
} else {
|
|
||||||
c.md.User = url.UserPassword(ss[0], ss[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if mm := mdata.GetStringMapString(md, header); len(mm) > 0 {
|
if mm := mdata.GetStringMapString(md, header); len(mm) > 0 {
|
||||||
hd := http.Header{}
|
hd := http.Header{}
|
||||||
for k, v := range mm {
|
for k, v := range mm {
|
||||||
|
@ -24,6 +24,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type http2Connector struct {
|
type http2Connector struct {
|
||||||
|
user *url.Userinfo
|
||||||
md metadata
|
md metadata
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
}
|
}
|
||||||
@ -35,6 +36,7 @@ func NewConnector(opts ...connector.Option) connector.Connector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &http2Connector{
|
return &http2Connector{
|
||||||
|
user: options.User,
|
||||||
logger: options.Logger,
|
logger: options.Logger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,7 +76,7 @@ func (c *http2Connector) Connect(ctx context.Context, conn net.Conn, network, ad
|
|||||||
req.Header.Set("User-Agent", c.md.UserAgent)
|
req.Header.Set("User-Agent", c.md.UserAgent)
|
||||||
}
|
}
|
||||||
|
|
||||||
if user := c.md.User; user != nil {
|
if user := c.user; user != nil {
|
||||||
u := user.Username()
|
u := user.Username()
|
||||||
p, _ := user.Password()
|
p, _ := user.Password()
|
||||||
req.Header.Set("Proxy-Authorization",
|
req.Header.Set("Proxy-Authorization",
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package http2
|
package http2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
mdata "github.com/go-gost/gost/pkg/metadata"
|
||||||
@ -15,14 +13,12 @@ const (
|
|||||||
type metadata struct {
|
type metadata struct {
|
||||||
connectTimeout time.Duration
|
connectTimeout time.Duration
|
||||||
UserAgent string
|
UserAgent string
|
||||||
User *url.Userinfo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *http2Connector) parseMetadata(md mdata.Metadata) (err error) {
|
func (c *http2Connector) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
const (
|
const (
|
||||||
connectTimeout = "timeout"
|
connectTimeout = "timeout"
|
||||||
userAgent = "userAgent"
|
userAgent = "userAgent"
|
||||||
user = "user"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
||||||
@ -31,14 +27,5 @@ func (c *http2Connector) parseMetadata(md mdata.Metadata) (err error) {
|
|||||||
c.md.UserAgent = defaultUserAgent
|
c.md.UserAgent = defaultUserAgent
|
||||||
}
|
}
|
||||||
|
|
||||||
if v := mdata.GetString(md, user); v != "" {
|
|
||||||
ss := strings.SplitN(v, ":", 2)
|
|
||||||
if len(ss) == 1 {
|
|
||||||
c.md.User = url.User(ss[0])
|
|
||||||
} else {
|
|
||||||
c.md.User = url.UserPassword(ss[0], ss[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,25 @@
|
|||||||
package connector
|
package connector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
"github.com/go-gost/gost/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
|
User *url.Userinfo
|
||||||
Logger logger.Logger
|
Logger logger.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
type Option func(opts *Options)
|
type Option func(opts *Options)
|
||||||
|
|
||||||
|
func UserOption(user *url.Userinfo) Option {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.User = user
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func LoggerOption(logger logger.Logger) Option {
|
func LoggerOption(logger logger.Logger) Option {
|
||||||
return func(opts *Options) {
|
return func(opts *Options) {
|
||||||
opts.Logger = logger
|
opts.Logger = logger
|
||||||
|
@ -79,10 +79,10 @@ func (c *relayConnector) bind(conn net.Conn, cmd uint8, network, address string)
|
|||||||
Flags: cmd,
|
Flags: cmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.md.user != nil {
|
if c.user != nil {
|
||||||
pwd, _ := c.md.user.Password()
|
pwd, _ := c.user.Password()
|
||||||
req.Features = append(req.Features, &relay.UserAuthFeature{
|
req.Features = append(req.Features, &relay.UserAuthFeature{
|
||||||
Username: c.md.user.Username(),
|
Username: c.user.Username(),
|
||||||
Password: pwd,
|
Password: pwd,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/socks"
|
"github.com/go-gost/gost/pkg/common/util/socks"
|
||||||
@ -19,6 +20,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type relayConnector struct {
|
type relayConnector struct {
|
||||||
|
user *url.Userinfo
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
md metadata
|
md metadata
|
||||||
}
|
}
|
||||||
@ -30,6 +32,7 @@ func NewConnector(opts ...connector.Option) connector.Connector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &relayConnector{
|
return &relayConnector{
|
||||||
|
user: options.User,
|
||||||
logger: options.Logger,
|
logger: options.Logger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,10 +74,10 @@ func (c *relayConnector) Connect(ctx context.Context, conn net.Conn, network, ad
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.md.user != nil {
|
if c.user != nil {
|
||||||
pwd, _ := c.md.user.Password()
|
pwd, _ := c.user.Password()
|
||||||
req.Features = append(req.Features, &relay.UserAuthFeature{
|
req.Features = append(req.Features, &relay.UserAuthFeature{
|
||||||
Username: c.md.user.Username(),
|
Username: c.user.Username(),
|
||||||
Password: pwd,
|
Password: pwd,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package relay
|
package relay
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
mdata "github.com/go-gost/gost/pkg/metadata"
|
||||||
@ -10,25 +8,15 @@ import (
|
|||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
connectTimeout time.Duration
|
connectTimeout time.Duration
|
||||||
user *url.Userinfo
|
|
||||||
noDelay bool
|
noDelay bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *relayConnector) parseMetadata(md mdata.Metadata) (err error) {
|
func (c *relayConnector) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
const (
|
const (
|
||||||
user = "user"
|
|
||||||
connectTimeout = "connectTimeout"
|
connectTimeout = "connectTimeout"
|
||||||
noDelay = "nodelay"
|
noDelay = "nodelay"
|
||||||
)
|
)
|
||||||
|
|
||||||
if v := mdata.GetString(md, user); v != "" {
|
|
||||||
ss := strings.SplitN(v, ":", 2)
|
|
||||||
if len(ss) == 1 {
|
|
||||||
c.md.user = url.User(ss[0])
|
|
||||||
} else {
|
|
||||||
c.md.user = url.UserPassword(ss[0], ss[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
||||||
c.md.noDelay = mdata.GetBool(md, noDelay)
|
c.md.noDelay = mdata.GetBool(md, noDelay)
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -21,6 +22,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type socks4Connector struct {
|
type socks4Connector struct {
|
||||||
|
user *url.Userinfo
|
||||||
md metadata
|
md metadata
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
}
|
}
|
||||||
@ -32,6 +34,7 @@ func NewConnector(opts ...connector.Option) connector.Connector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &socks4Connector{
|
return &socks4Connector{
|
||||||
|
user: options.User,
|
||||||
logger: options.Logger,
|
logger: options.Logger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,7 +99,11 @@ func (c *socks4Connector) Connect(ctx context.Context, conn net.Conn, network, a
|
|||||||
defer conn.SetDeadline(time.Time{})
|
defer conn.SetDeadline(time.Time{})
|
||||||
}
|
}
|
||||||
|
|
||||||
req := gosocks4.NewRequest(gosocks4.CmdConnect, addr, nil)
|
var userid []byte
|
||||||
|
if c.user != nil && c.user.Username() != "" {
|
||||||
|
userid = []byte(c.user.Username())
|
||||||
|
}
|
||||||
|
req := gosocks4.NewRequest(gosocks4.CmdConnect, addr, userid)
|
||||||
if err := req.Write(conn); err != nil {
|
if err := req.Write(conn); err != nil {
|
||||||
c.logger.Error(err)
|
c.logger.Error(err)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package v4
|
package v4
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/url"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
mdata "github.com/go-gost/gost/pkg/metadata"
|
||||||
@ -9,20 +8,15 @@ import (
|
|||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
connectTimeout time.Duration
|
connectTimeout time.Duration
|
||||||
User *url.Userinfo
|
|
||||||
disable4a bool
|
disable4a bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *socks4Connector) parseMetadata(md mdata.Metadata) (err error) {
|
func (c *socks4Connector) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
const (
|
const (
|
||||||
connectTimeout = "timeout"
|
connectTimeout = "timeout"
|
||||||
user = "user"
|
|
||||||
disable4a = "disable4a"
|
disable4a = "disable4a"
|
||||||
)
|
)
|
||||||
|
|
||||||
if v := mdata.GetString(md, user); v != "" {
|
|
||||||
c.md.User = url.User(v)
|
|
||||||
}
|
|
||||||
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
||||||
c.md.disable4a = mdata.GetBool(md, disable4a)
|
c.md.disable4a = mdata.GetBool(md, disable4a)
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-gost/gosocks5"
|
"github.com/go-gost/gosocks5"
|
||||||
@ -23,6 +24,7 @@ func init() {
|
|||||||
|
|
||||||
type socks5Connector struct {
|
type socks5Connector struct {
|
||||||
selector gosocks5.Selector
|
selector gosocks5.Selector
|
||||||
|
user *url.Userinfo
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
md metadata
|
md metadata
|
||||||
}
|
}
|
||||||
@ -34,6 +36,7 @@ func NewConnector(opts ...connector.Option) connector.Connector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &socks5Connector{
|
return &socks5Connector{
|
||||||
|
user: options.User,
|
||||||
logger: options.Logger,
|
logger: options.Logger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,7 +52,7 @@ func (c *socks5Connector) Init(md md.Metadata) (err error) {
|
|||||||
gosocks5.MethodUserPass,
|
gosocks5.MethodUserPass,
|
||||||
},
|
},
|
||||||
logger: c.logger,
|
logger: c.logger,
|
||||||
User: c.md.User,
|
User: c.user,
|
||||||
TLSConfig: c.md.tlsConfig,
|
TLSConfig: c.md.tlsConfig,
|
||||||
}
|
}
|
||||||
if !c.md.noTLS {
|
if !c.md.noTLS {
|
||||||
|
@ -2,8 +2,6 @@ package v5
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
mdata "github.com/go-gost/gost/pkg/metadata"
|
||||||
@ -11,7 +9,6 @@ import (
|
|||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
connectTimeout time.Duration
|
connectTimeout time.Duration
|
||||||
User *url.Userinfo
|
|
||||||
tlsConfig *tls.Config
|
tlsConfig *tls.Config
|
||||||
noTLS bool
|
noTLS bool
|
||||||
}
|
}
|
||||||
@ -19,19 +16,9 @@ type metadata struct {
|
|||||||
func (c *socks5Connector) parseMetadata(md mdata.Metadata) (err error) {
|
func (c *socks5Connector) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
const (
|
const (
|
||||||
connectTimeout = "timeout"
|
connectTimeout = "timeout"
|
||||||
user = "user"
|
|
||||||
noTLS = "notls"
|
noTLS = "notls"
|
||||||
)
|
)
|
||||||
|
|
||||||
if v := mdata.GetString(md, user); v != "" {
|
|
||||||
ss := strings.SplitN(v, ":", 2)
|
|
||||||
if len(ss) == 1 {
|
|
||||||
c.md.User = url.User(ss[0])
|
|
||||||
} else {
|
|
||||||
c.md.User = url.UserPassword(ss[0], ss[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
||||||
c.md.noTLS = mdata.GetBool(md, noTLS)
|
c.md.noTLS = mdata.GetBool(md, noTLS)
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-gost/gosocks5"
|
"github.com/go-gost/gosocks5"
|
||||||
@ -13,6 +14,7 @@ import (
|
|||||||
"github.com/go-gost/gost/pkg/logger"
|
"github.com/go-gost/gost/pkg/logger"
|
||||||
md "github.com/go-gost/gost/pkg/metadata"
|
md "github.com/go-gost/gost/pkg/metadata"
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
"github.com/go-gost/gost/pkg/registry"
|
||||||
|
"github.com/shadowsocks/go-shadowsocks2/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -20,6 +22,8 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ssConnector struct {
|
type ssConnector struct {
|
||||||
|
user *url.Userinfo
|
||||||
|
cipher core.Cipher
|
||||||
md metadata
|
md metadata
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
}
|
}
|
||||||
@ -31,12 +35,23 @@ func NewConnector(opts ...connector.Option) connector.Connector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &ssConnector{
|
return &ssConnector{
|
||||||
|
user: options.User,
|
||||||
logger: options.Logger,
|
logger: options.Logger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ssConnector) Init(md md.Metadata) (err error) {
|
func (c *ssConnector) Init(md md.Metadata) (err error) {
|
||||||
return c.parseMetadata(md)
|
if err = c.parseMetadata(md); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.user != nil {
|
||||||
|
method := c.user.Username()
|
||||||
|
password, _ := c.user.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) {
|
func (c *ssConnector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
|
||||||
@ -80,8 +95,8 @@ func (c *ssConnector) Connect(ctx context.Context, conn net.Conn, network, addre
|
|||||||
defer conn.SetDeadline(time.Time{})
|
defer conn.SetDeadline(time.Time{})
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.md.cipher != nil {
|
if c.cipher != nil {
|
||||||
conn = c.md.cipher.StreamConn(conn)
|
conn = c.cipher.StreamConn(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
var sc net.Conn
|
var sc net.Conn
|
||||||
|
@ -1,42 +1,25 @@
|
|||||||
package ss
|
package ss
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/ss"
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
mdata "github.com/go-gost/gost/pkg/metadata"
|
||||||
"github.com/shadowsocks/go-shadowsocks2/core"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
cipher core.Cipher
|
key string
|
||||||
connectTimeout time.Duration
|
connectTimeout time.Duration
|
||||||
noDelay bool
|
noDelay bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ssConnector) parseMetadata(md mdata.Metadata) (err error) {
|
func (c *ssConnector) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
const (
|
const (
|
||||||
user = "user"
|
|
||||||
key = "key"
|
key = "key"
|
||||||
connectTimeout = "timeout"
|
connectTimeout = "timeout"
|
||||||
noDelay = "nodelay"
|
noDelay = "nodelay"
|
||||||
)
|
)
|
||||||
|
|
||||||
var method, password string
|
c.md.key = mdata.GetString(md, key)
|
||||||
if v := mdata.GetString(md, user); v != "" {
|
|
||||||
ss := strings.SplitN(v, ":", 2)
|
|
||||||
if len(ss) == 1 {
|
|
||||||
method = ss[0]
|
|
||||||
} else {
|
|
||||||
method, password = ss[0], ss[1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.md.cipher, err = ss.ShadowCipher(method, password, mdata.GetString(md, key))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
||||||
c.md.noDelay = mdata.GetBool(md, noDelay)
|
c.md.noDelay = mdata.GetBool(md, noDelay)
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/socks"
|
"github.com/go-gost/gost/pkg/common/util/socks"
|
||||||
@ -12,6 +13,7 @@ import (
|
|||||||
"github.com/go-gost/gost/pkg/logger"
|
"github.com/go-gost/gost/pkg/logger"
|
||||||
md "github.com/go-gost/gost/pkg/metadata"
|
md "github.com/go-gost/gost/pkg/metadata"
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
"github.com/go-gost/gost/pkg/registry"
|
||||||
|
"github.com/shadowsocks/go-shadowsocks2/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -19,6 +21,8 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ssuConnector struct {
|
type ssuConnector struct {
|
||||||
|
user *url.Userinfo
|
||||||
|
cipher core.Cipher
|
||||||
md metadata
|
md metadata
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
}
|
}
|
||||||
@ -30,12 +34,23 @@ func NewConnector(opts ...connector.Option) connector.Connector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &ssuConnector{
|
return &ssuConnector{
|
||||||
|
user: options.User,
|
||||||
logger: options.Logger,
|
logger: options.Logger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ssuConnector) Init(md md.Metadata) (err error) {
|
func (c *ssuConnector) Init(md md.Metadata) (err error) {
|
||||||
return c.parseMetadata(md)
|
if err = c.parseMetadata(md); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.user != nil {
|
||||||
|
method := c.user.Username()
|
||||||
|
password, _ := c.user.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) {
|
func (c *ssuConnector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
|
||||||
@ -67,16 +82,16 @@ func (c *ssuConnector) Connect(ctx context.Context, conn net.Conn, network, addr
|
|||||||
|
|
||||||
pc, ok := conn.(net.PacketConn)
|
pc, ok := conn.(net.PacketConn)
|
||||||
if ok {
|
if ok {
|
||||||
if c.md.cipher != nil {
|
if c.cipher != nil {
|
||||||
pc = c.md.cipher.PacketConn(pc)
|
pc = c.cipher.PacketConn(pc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// standard UDP relay
|
// standard UDP relay
|
||||||
return ss.UDPClientConn(pc, conn.RemoteAddr(), taddr, c.md.bufferSize), nil
|
return ss.UDPClientConn(pc, conn.RemoteAddr(), taddr, c.md.bufferSize), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.md.cipher != nil {
|
if c.cipher != nil {
|
||||||
conn = ss.ShadowConn(c.md.cipher.StreamConn(conn), nil)
|
conn = ss.ShadowConn(c.cipher.StreamConn(conn), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UDP over TCP
|
// UDP over TCP
|
||||||
|
@ -2,42 +2,25 @@ package ss
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/ss"
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
mdata "github.com/go-gost/gost/pkg/metadata"
|
||||||
"github.com/shadowsocks/go-shadowsocks2/core"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
cipher core.Cipher
|
key string
|
||||||
connectTimeout time.Duration
|
connectTimeout time.Duration
|
||||||
bufferSize int
|
bufferSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ssuConnector) parseMetadata(md mdata.Metadata) (err error) {
|
func (c *ssuConnector) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
const (
|
const (
|
||||||
user = "user"
|
|
||||||
key = "key"
|
key = "key"
|
||||||
connectTimeout = "timeout"
|
connectTimeout = "timeout"
|
||||||
bufferSize = "bufferSize" // udp buffer size
|
bufferSize = "bufferSize" // udp buffer size
|
||||||
)
|
)
|
||||||
|
|
||||||
var method, password string
|
c.md.key = mdata.GetString(md, key)
|
||||||
if v := mdata.GetString(md, user); v != "" {
|
|
||||||
ss := strings.SplitN(v, ":", 2)
|
|
||||||
if len(ss) == 1 {
|
|
||||||
method = ss[0]
|
|
||||||
} else {
|
|
||||||
method, password = ss[0], ss[1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.md.cipher, err = ss.ShadowCipher(method, password, mdata.GetString(md, key))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
||||||
|
|
||||||
if bs := mdata.GetInt(md, bufferSize); bs > 0 {
|
if bs := mdata.GetInt(md, bufferSize); bs > 0 {
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
|
"net/url"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -20,6 +21,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type forwardDialer struct {
|
type forwardDialer struct {
|
||||||
|
user *url.Userinfo
|
||||||
sessions map[string]*sshSession
|
sessions map[string]*sshSession
|
||||||
sessionMutex sync.Mutex
|
sessionMutex sync.Mutex
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
@ -33,6 +35,7 @@ func NewDialer(opts ...dialer.Option) dialer.Dialer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &forwardDialer{
|
return &forwardDialer{
|
||||||
|
user: options.User,
|
||||||
sessions: make(map[string]*sshSession),
|
sessions: make(map[string]*sshSession),
|
||||||
logger: options.Logger,
|
logger: options.Logger,
|
||||||
}
|
}
|
||||||
@ -161,9 +164,9 @@ func (d *forwardDialer) initSession(ctx context.Context, addr string, conn net.C
|
|||||||
// Timeout: timeout,
|
// Timeout: timeout,
|
||||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
if d.md.user != nil {
|
if d.user != nil {
|
||||||
config.User = d.md.user.Username()
|
config.User = d.user.Username()
|
||||||
if password, _ := d.md.user.Password(); password != "" {
|
if password, _ := d.user.Password(); password != "" {
|
||||||
config.Auth = []ssh.AuthMethod{
|
config.Auth = []ssh.AuthMethod{
|
||||||
ssh.Password(password),
|
ssh.Password(password),
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,6 @@ package ssh
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
mdata "github.com/go-gost/gost/pkg/metadata"
|
||||||
@ -12,27 +10,16 @@ import (
|
|||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
handshakeTimeout time.Duration
|
handshakeTimeout time.Duration
|
||||||
user *url.Userinfo
|
|
||||||
signer ssh.Signer
|
signer ssh.Signer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *forwardDialer) parseMetadata(md mdata.Metadata) (err error) {
|
func (d *forwardDialer) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
const (
|
const (
|
||||||
handshakeTimeout = "handshakeTimeout"
|
handshakeTimeout = "handshakeTimeout"
|
||||||
user = "user"
|
|
||||||
privateKeyFile = "privateKeyFile"
|
privateKeyFile = "privateKeyFile"
|
||||||
passphrase = "passphrase"
|
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 != "" {
|
if key := mdata.GetString(md, privateKeyFile); key != "" {
|
||||||
data, err := ioutil.ReadFile(key)
|
data, err := ioutil.ReadFile(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -3,16 +3,24 @@ package dialer
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
"github.com/go-gost/gost/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
|
User *url.Userinfo
|
||||||
Logger logger.Logger
|
Logger logger.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
type Option func(opts *Options)
|
type Option func(opts *Options)
|
||||||
|
|
||||||
|
func UserOption(user *url.Userinfo) Option {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.User = user
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func LoggerOption(logger logger.Logger) Option {
|
func LoggerOption(logger logger.Logger) Option {
|
||||||
return func(opts *Options) {
|
return func(opts *Options) {
|
||||||
opts.Logger = logger
|
opts.Logger = logger
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-gost/gost/pkg/auth"
|
||||||
"github.com/go-gost/gost/pkg/bypass"
|
"github.com/go-gost/gost/pkg/bypass"
|
||||||
"github.com/go-gost/gost/pkg/chain"
|
"github.com/go-gost/gost/pkg/chain"
|
||||||
"github.com/go-gost/gost/pkg/handler"
|
"github.com/go-gost/gost/pkg/handler"
|
||||||
@ -34,6 +35,7 @@ type forwardHandler struct {
|
|||||||
bypass bypass.Bypass
|
bypass bypass.Bypass
|
||||||
config *ssh.ServerConfig
|
config *ssh.ServerConfig
|
||||||
router *chain.Router
|
router *chain.Router
|
||||||
|
authenticator auth.Authenticator
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
md metadata
|
md metadata
|
||||||
}
|
}
|
||||||
@ -57,13 +59,13 @@ func (h *forwardHandler) Init(md md.Metadata) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
config := &ssh.ServerConfig{
|
config := &ssh.ServerConfig{
|
||||||
PasswordCallback: ssh_util.PasswordCallback(h.md.authenticator),
|
PasswordCallback: ssh_util.PasswordCallback(h.authenticator),
|
||||||
PublicKeyCallback: ssh_util.PublicKeyCallback(h.md.authorizedKeys),
|
PublicKeyCallback: ssh_util.PublicKeyCallback(h.md.authorizedKeys),
|
||||||
}
|
}
|
||||||
|
|
||||||
config.AddHostKey(h.md.signer)
|
config.AddHostKey(h.md.signer)
|
||||||
|
|
||||||
if h.md.authenticator == nil && len(h.md.authorizedKeys) == 0 {
|
if h.authenticator == nil && len(h.md.authorizedKeys) == 0 {
|
||||||
config.NoClientAuth = true
|
config.NoClientAuth = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,9 +2,7 @@ package ssh
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/auth"
|
|
||||||
tls_util "github.com/go-gost/gost/pkg/common/util/tls"
|
tls_util "github.com/go-gost/gost/pkg/common/util/tls"
|
||||||
ssh_util "github.com/go-gost/gost/pkg/internal/util/ssh"
|
ssh_util "github.com/go-gost/gost/pkg/internal/util/ssh"
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
mdata "github.com/go-gost/gost/pkg/metadata"
|
||||||
@ -12,32 +10,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
authenticator auth.Authenticator
|
|
||||||
signer ssh.Signer
|
signer ssh.Signer
|
||||||
authorizedKeys map[string]bool
|
authorizedKeys map[string]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *forwardHandler) parseMetadata(md mdata.Metadata) (err error) {
|
func (h *forwardHandler) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
const (
|
const (
|
||||||
users = "users"
|
|
||||||
authorizedKeys = "authorizedKeys"
|
authorizedKeys = "authorizedKeys"
|
||||||
privateKeyFile = "privateKeyFile"
|
privateKeyFile = "privateKeyFile"
|
||||||
passphrase = "passphrase"
|
passphrase = "passphrase"
|
||||||
)
|
)
|
||||||
|
|
||||||
if auths := mdata.GetStrings(md, users); len(auths) > 0 {
|
|
||||||
authenticator := auth.NewLocalAuthenticator(nil)
|
|
||||||
for _, auth := range auths {
|
|
||||||
ss := strings.SplitN(auth, ":", 2)
|
|
||||||
if len(ss) == 1 {
|
|
||||||
authenticator.Add(ss[0], "")
|
|
||||||
} else {
|
|
||||||
authenticator.Add(ss[0], ss[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
h.md.authenticator = authenticator
|
|
||||||
}
|
|
||||||
|
|
||||||
if key := mdata.GetString(md, privateKeyFile); key != "" {
|
if key := mdata.GetString(md, privateKeyFile); key != "" {
|
||||||
data, err := ioutil.ReadFile(key)
|
data, err := ioutil.ReadFile(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/asaskevich/govalidator"
|
"github.com/asaskevich/govalidator"
|
||||||
|
"github.com/go-gost/gost/pkg/auth"
|
||||||
"github.com/go-gost/gost/pkg/bypass"
|
"github.com/go-gost/gost/pkg/bypass"
|
||||||
"github.com/go-gost/gost/pkg/chain"
|
"github.com/go-gost/gost/pkg/chain"
|
||||||
"github.com/go-gost/gost/pkg/handler"
|
"github.com/go-gost/gost/pkg/handler"
|
||||||
@ -31,6 +32,7 @@ func init() {
|
|||||||
type httpHandler struct {
|
type httpHandler struct {
|
||||||
bypass bypass.Bypass
|
bypass bypass.Bypass
|
||||||
router *chain.Router
|
router *chain.Router
|
||||||
|
authenticator auth.Authenticator
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
md metadata
|
md metadata
|
||||||
}
|
}
|
||||||
@ -260,7 +262,7 @@ func (h *httpHandler) basicProxyAuth(proxyAuth string) (username, password strin
|
|||||||
|
|
||||||
func (h *httpHandler) authenticate(conn net.Conn, req *http.Request, resp *http.Response) (ok bool) {
|
func (h *httpHandler) authenticate(conn net.Conn, req *http.Request, resp *http.Response) (ok bool) {
|
||||||
u, p, _ := h.basicProxyAuth(req.Header.Get("Proxy-Authorization"))
|
u, p, _ := h.basicProxyAuth(req.Header.Get("Proxy-Authorization"))
|
||||||
if h.md.authenticator == nil || h.md.authenticator.Authenticate(u, p) {
|
if h.authenticator == nil || h.authenticator.Authenticate(u, p) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,12 +4,10 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/auth"
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
mdata "github.com/go-gost/gost/pkg/metadata"
|
||||||
)
|
)
|
||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
authenticator auth.Authenticator
|
|
||||||
probeResist *probeResist
|
probeResist *probeResist
|
||||||
sni bool
|
sni bool
|
||||||
enableUDP bool
|
enableUDP bool
|
||||||
@ -19,26 +17,12 @@ type metadata struct {
|
|||||||
func (h *httpHandler) parseMetadata(md mdata.Metadata) error {
|
func (h *httpHandler) parseMetadata(md mdata.Metadata) error {
|
||||||
const (
|
const (
|
||||||
header = "header"
|
header = "header"
|
||||||
users = "users"
|
|
||||||
probeResistKey = "probeResist"
|
probeResistKey = "probeResist"
|
||||||
knock = "knock"
|
knock = "knock"
|
||||||
sni = "sni"
|
sni = "sni"
|
||||||
enableUDP = "udp"
|
enableUDP = "udp"
|
||||||
)
|
)
|
||||||
|
|
||||||
if auths := mdata.GetStrings(md, users); len(auths) > 0 {
|
|
||||||
authenticator := auth.NewLocalAuthenticator(nil)
|
|
||||||
for _, auth := range auths {
|
|
||||||
ss := strings.SplitN(auth, ":", 2)
|
|
||||||
if len(ss) == 1 {
|
|
||||||
authenticator.Add(ss[0], "")
|
|
||||||
} else {
|
|
||||||
authenticator.Add(ss[0], ss[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
h.md.authenticator = authenticator
|
|
||||||
}
|
|
||||||
|
|
||||||
if m := mdata.GetStringMapString(md, header); len(m) > 0 {
|
if m := mdata.GetStringMapString(md, header); len(m) > 0 {
|
||||||
hd := http.Header{}
|
hd := http.Header{}
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/asaskevich/govalidator"
|
"github.com/asaskevich/govalidator"
|
||||||
|
"github.com/go-gost/gost/pkg/auth"
|
||||||
"github.com/go-gost/gost/pkg/bypass"
|
"github.com/go-gost/gost/pkg/bypass"
|
||||||
"github.com/go-gost/gost/pkg/chain"
|
"github.com/go-gost/gost/pkg/chain"
|
||||||
"github.com/go-gost/gost/pkg/handler"
|
"github.com/go-gost/gost/pkg/handler"
|
||||||
@ -31,6 +32,7 @@ func init() {
|
|||||||
type http2Handler struct {
|
type http2Handler struct {
|
||||||
bypass bypass.Bypass
|
bypass bypass.Bypass
|
||||||
router *chain.Router
|
router *chain.Router
|
||||||
|
authenticator auth.Authenticator
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
md metadata
|
md metadata
|
||||||
}
|
}
|
||||||
@ -392,7 +394,7 @@ func (h *http2Handler) basicProxyAuth(proxyAuth string) (username, password stri
|
|||||||
|
|
||||||
func (h *http2Handler) authenticate(conn net.Conn, req *http.Request, resp *http.Response) (ok bool) {
|
func (h *http2Handler) authenticate(conn net.Conn, req *http.Request, resp *http.Response) (ok bool) {
|
||||||
u, p, _ := h.basicProxyAuth(req.Header.Get("Proxy-Authorization"))
|
u, p, _ := h.basicProxyAuth(req.Header.Get("Proxy-Authorization"))
|
||||||
if h.md.authenticator == nil || h.md.authenticator.Authenticate(u, p) {
|
if h.authenticator == nil || h.authenticator.Authenticate(u, p) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,12 +3,10 @@ package http2
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/auth"
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
mdata "github.com/go-gost/gost/pkg/metadata"
|
||||||
)
|
)
|
||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
authenticator auth.Authenticator
|
|
||||||
proxyAgent string
|
proxyAgent string
|
||||||
probeResist *probeResist
|
probeResist *probeResist
|
||||||
sni bool
|
sni bool
|
||||||
@ -18,7 +16,6 @@ type metadata struct {
|
|||||||
func (h *http2Handler) parseMetadata(md mdata.Metadata) error {
|
func (h *http2Handler) parseMetadata(md mdata.Metadata) error {
|
||||||
const (
|
const (
|
||||||
proxyAgent = "proxyAgent"
|
proxyAgent = "proxyAgent"
|
||||||
users = "users"
|
|
||||||
probeResistKey = "probeResist"
|
probeResistKey = "probeResist"
|
||||||
knock = "knock"
|
knock = "knock"
|
||||||
sni = "sni"
|
sni = "sni"
|
||||||
@ -27,19 +24,6 @@ func (h *http2Handler) parseMetadata(md mdata.Metadata) error {
|
|||||||
|
|
||||||
h.md.proxyAgent = mdata.GetString(md, proxyAgent)
|
h.md.proxyAgent = mdata.GetString(md, proxyAgent)
|
||||||
|
|
||||||
if auths := mdata.GetStrings(md, users); len(auths) > 0 {
|
|
||||||
authenticator := auth.NewLocalAuthenticator(nil)
|
|
||||||
for _, auth := range auths {
|
|
||||||
ss := strings.SplitN(auth, ":", 2)
|
|
||||||
if len(ss) == 1 {
|
|
||||||
authenticator.Add(ss[0], "")
|
|
||||||
} else {
|
|
||||||
authenticator.Add(ss[0], ss[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
h.md.authenticator = authenticator
|
|
||||||
}
|
|
||||||
|
|
||||||
if v := mdata.GetString(md, probeResistKey); v != "" {
|
if v := mdata.GetString(md, probeResistKey); v != "" {
|
||||||
if ss := strings.SplitN(v, ":", 2); len(ss) == 2 {
|
if ss := strings.SplitN(v, ":", 2); len(ss) == 2 {
|
||||||
h.md.probeResist = &probeResist{
|
h.md.probeResist = &probeResist{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/go-gost/gost/pkg/auth"
|
||||||
"github.com/go-gost/gost/pkg/bypass"
|
"github.com/go-gost/gost/pkg/bypass"
|
||||||
"github.com/go-gost/gost/pkg/chain"
|
"github.com/go-gost/gost/pkg/chain"
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
"github.com/go-gost/gost/pkg/logger"
|
||||||
@ -11,6 +12,7 @@ type Options struct {
|
|||||||
Router *chain.Router
|
Router *chain.Router
|
||||||
Bypass bypass.Bypass
|
Bypass bypass.Bypass
|
||||||
Resolver resolver.Resolver
|
Resolver resolver.Resolver
|
||||||
|
Authenticator auth.Authenticator
|
||||||
Logger logger.Logger
|
Logger logger.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,6 +30,12 @@ func BypassOption(bypass bypass.Bypass) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AuthenticatorOption(auth auth.Authenticator) Option {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.Authenticator = auth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func LoggerOption(logger logger.Logger) Option {
|
func LoggerOption(logger logger.Logger) Option {
|
||||||
return func(opts *Options) {
|
return func(opts *Options) {
|
||||||
opts.Logger = logger
|
opts.Logger = logger
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-gost/gost/pkg/auth"
|
||||||
"github.com/go-gost/gost/pkg/bypass"
|
"github.com/go-gost/gost/pkg/bypass"
|
||||||
"github.com/go-gost/gost/pkg/chain"
|
"github.com/go-gost/gost/pkg/chain"
|
||||||
"github.com/go-gost/gost/pkg/handler"
|
"github.com/go-gost/gost/pkg/handler"
|
||||||
@ -23,6 +24,7 @@ type relayHandler struct {
|
|||||||
group *chain.NodeGroup
|
group *chain.NodeGroup
|
||||||
bypass bypass.Bypass
|
bypass bypass.Bypass
|
||||||
router *chain.Router
|
router *chain.Router
|
||||||
|
authenticator auth.Authenticator
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
md metadata
|
md metadata
|
||||||
}
|
}
|
||||||
@ -107,7 +109,7 @@ func (h *relayHandler) Handle(ctx context.Context, conn net.Conn) {
|
|||||||
Version: relay.Version1,
|
Version: relay.Version1,
|
||||||
Status: relay.StatusOK,
|
Status: relay.StatusOK,
|
||||||
}
|
}
|
||||||
if h.md.authenticator != nil && !h.md.authenticator.Authenticate(user, pass) {
|
if h.authenticator != nil && !h.authenticator.Authenticate(user, pass) {
|
||||||
resp.Status = relay.StatusUnauthorized
|
resp.Status = relay.StatusUnauthorized
|
||||||
resp.WriteTo(conn)
|
resp.WriteTo(conn)
|
||||||
h.logger.Error("unauthorized")
|
h.logger.Error("unauthorized")
|
||||||
|
@ -2,15 +2,12 @@ package relay
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/auth"
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
mdata "github.com/go-gost/gost/pkg/metadata"
|
||||||
)
|
)
|
||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
authenticator auth.Authenticator
|
|
||||||
readTimeout time.Duration
|
readTimeout time.Duration
|
||||||
enableBind bool
|
enableBind bool
|
||||||
udpBufferSize int
|
udpBufferSize int
|
||||||
@ -19,26 +16,12 @@ type metadata struct {
|
|||||||
|
|
||||||
func (h *relayHandler) parseMetadata(md mdata.Metadata) (err error) {
|
func (h *relayHandler) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
const (
|
const (
|
||||||
users = "users"
|
|
||||||
readTimeout = "readTimeout"
|
readTimeout = "readTimeout"
|
||||||
enableBind = "bind"
|
enableBind = "bind"
|
||||||
udpBufferSize = "udpBufferSize"
|
udpBufferSize = "udpBufferSize"
|
||||||
noDelay = "nodelay"
|
noDelay = "nodelay"
|
||||||
)
|
)
|
||||||
|
|
||||||
if auths := mdata.GetStrings(md, users); len(auths) > 0 {
|
|
||||||
authenticator := auth.NewLocalAuthenticator(nil)
|
|
||||||
for _, auth := range auths {
|
|
||||||
ss := strings.SplitN(auth, ":", 2)
|
|
||||||
if len(ss) == 1 {
|
|
||||||
authenticator.Add(ss[0], "")
|
|
||||||
} else {
|
|
||||||
authenticator.Add(ss[0], ss[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
h.md.authenticator = authenticator
|
|
||||||
}
|
|
||||||
|
|
||||||
h.md.readTimeout = mdata.GetDuration(md, readTimeout)
|
h.md.readTimeout = mdata.GetDuration(md, readTimeout)
|
||||||
h.md.enableBind = mdata.GetBool(md, enableBind)
|
h.md.enableBind = mdata.GetBool(md, enableBind)
|
||||||
h.md.noDelay = mdata.GetBool(md, noDelay)
|
h.md.noDelay = mdata.GetBool(md, noDelay)
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-gost/gosocks4"
|
"github.com/go-gost/gosocks4"
|
||||||
|
"github.com/go-gost/gost/pkg/auth"
|
||||||
"github.com/go-gost/gost/pkg/bypass"
|
"github.com/go-gost/gost/pkg/bypass"
|
||||||
"github.com/go-gost/gost/pkg/chain"
|
"github.com/go-gost/gost/pkg/chain"
|
||||||
"github.com/go-gost/gost/pkg/handler"
|
"github.com/go-gost/gost/pkg/handler"
|
||||||
@ -22,6 +23,7 @@ func init() {
|
|||||||
type socks4Handler struct {
|
type socks4Handler struct {
|
||||||
bypass bypass.Bypass
|
bypass bypass.Bypass
|
||||||
router *chain.Router
|
router *chain.Router
|
||||||
|
authenticator auth.Authenticator
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
md metadata
|
md metadata
|
||||||
}
|
}
|
||||||
@ -77,8 +79,8 @@ func (h *socks4Handler) Handle(ctx context.Context, conn net.Conn) {
|
|||||||
|
|
||||||
conn.SetReadDeadline(time.Time{})
|
conn.SetReadDeadline(time.Time{})
|
||||||
|
|
||||||
if h.md.authenticator != nil &&
|
if h.authenticator != nil &&
|
||||||
!h.md.authenticator.Authenticate(string(req.Userid), "") {
|
!h.authenticator.Authenticate(string(req.Userid), "") {
|
||||||
resp := gosocks4.NewReply(gosocks4.RejectedUserid, nil)
|
resp := gosocks4.NewReply(gosocks4.RejectedUserid, nil)
|
||||||
resp.Write(conn)
|
resp.Write(conn)
|
||||||
h.logger.Debug(resp)
|
h.logger.Debug(resp)
|
||||||
|
@ -3,31 +3,18 @@ package v4
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/auth"
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
mdata "github.com/go-gost/gost/pkg/metadata"
|
||||||
)
|
)
|
||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
authenticator auth.Authenticator
|
|
||||||
readTimeout time.Duration
|
readTimeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *socks4Handler) parseMetadata(md mdata.Metadata) (err error) {
|
func (h *socks4Handler) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
const (
|
const (
|
||||||
users = "users"
|
|
||||||
readTimeout = "readTimeout"
|
readTimeout = "readTimeout"
|
||||||
)
|
)
|
||||||
|
|
||||||
if auths := mdata.GetStrings(md, users); len(auths) > 0 {
|
|
||||||
authenticator := auth.NewLocalAuthenticator(nil)
|
|
||||||
for _, auth := range auths {
|
|
||||||
if auth != "" {
|
|
||||||
authenticator.Add(auth, "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
h.md.authenticator = authenticator
|
|
||||||
}
|
|
||||||
|
|
||||||
h.md.readTimeout = mdata.GetDuration(md, readTimeout)
|
h.md.readTimeout = mdata.GetDuration(md, readTimeout)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-gost/gosocks5"
|
"github.com/go-gost/gosocks5"
|
||||||
|
"github.com/go-gost/gost/pkg/auth"
|
||||||
"github.com/go-gost/gost/pkg/bypass"
|
"github.com/go-gost/gost/pkg/bypass"
|
||||||
"github.com/go-gost/gost/pkg/chain"
|
"github.com/go-gost/gost/pkg/chain"
|
||||||
"github.com/go-gost/gost/pkg/common/util/socks"
|
"github.com/go-gost/gost/pkg/common/util/socks"
|
||||||
@ -24,6 +25,7 @@ type socks5Handler struct {
|
|||||||
selector gosocks5.Selector
|
selector gosocks5.Selector
|
||||||
bypass bypass.Bypass
|
bypass bypass.Bypass
|
||||||
router *chain.Router
|
router *chain.Router
|
||||||
|
authenticator auth.Authenticator
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
md metadata
|
md metadata
|
||||||
}
|
}
|
||||||
@ -47,7 +49,7 @@ func (h *socks5Handler) Init(md md.Metadata) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
h.selector = &serverSelector{
|
h.selector = &serverSelector{
|
||||||
Authenticator: h.md.authenticator,
|
Authenticator: h.authenticator,
|
||||||
TLSConfig: h.md.tlsConfig,
|
TLSConfig: h.md.tlsConfig,
|
||||||
logger: h.logger,
|
logger: h.logger,
|
||||||
noTLS: h.md.noTLS,
|
noTLS: h.md.noTLS,
|
||||||
|
@ -3,17 +3,14 @@ package v5
|
|||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/auth"
|
|
||||||
tls_util "github.com/go-gost/gost/pkg/common/util/tls"
|
tls_util "github.com/go-gost/gost/pkg/common/util/tls"
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
mdata "github.com/go-gost/gost/pkg/metadata"
|
||||||
)
|
)
|
||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
tlsConfig *tls.Config
|
tlsConfig *tls.Config
|
||||||
authenticator auth.Authenticator
|
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
readTimeout time.Duration
|
readTimeout time.Duration
|
||||||
noTLS bool
|
noTLS bool
|
||||||
@ -28,7 +25,6 @@ func (h *socks5Handler) parseMetadata(md mdata.Metadata) (err error) {
|
|||||||
certFile = "certFile"
|
certFile = "certFile"
|
||||||
keyFile = "keyFile"
|
keyFile = "keyFile"
|
||||||
caFile = "caFile"
|
caFile = "caFile"
|
||||||
users = "users"
|
|
||||||
readTimeout = "readTimeout"
|
readTimeout = "readTimeout"
|
||||||
timeout = "timeout"
|
timeout = "timeout"
|
||||||
noTLS = "notls"
|
noTLS = "notls"
|
||||||
@ -47,19 +43,6 @@ func (h *socks5Handler) parseMetadata(md mdata.Metadata) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if auths := mdata.GetStrings(md, users); len(auths) > 0 {
|
|
||||||
authenticator := auth.NewLocalAuthenticator(nil)
|
|
||||||
for _, auth := range auths {
|
|
||||||
ss := strings.SplitN(auth, ":", 2)
|
|
||||||
if len(ss) == 1 {
|
|
||||||
authenticator.Add(ss[0], "")
|
|
||||||
} else {
|
|
||||||
authenticator.Add(ss[0], ss[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
h.md.authenticator = authenticator
|
|
||||||
}
|
|
||||||
|
|
||||||
h.md.readTimeout = mdata.GetDuration(md, readTimeout)
|
h.md.readTimeout = mdata.GetDuration(md, readTimeout)
|
||||||
h.md.timeout = mdata.GetDuration(md, timeout)
|
h.md.timeout = mdata.GetDuration(md, timeout)
|
||||||
h.md.noTLS = mdata.GetBool(md, noTLS)
|
h.md.noTLS = mdata.GetBool(md, noTLS)
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package listener
|
package listener
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/go-gost/gost/pkg/auth"
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
"github.com/go-gost/gost/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
Addr string
|
Addr string
|
||||||
|
Authenticator auth.Authenticator
|
||||||
Logger logger.Logger
|
Logger logger.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,6 +19,12 @@ func AddrOption(addr string) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AuthenticatorOption(auth auth.Authenticator) Option {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.Authenticator = auth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func LoggerOption(logger logger.Logger) Option {
|
func LoggerOption(logger logger.Logger) Option {
|
||||||
return func(opts *Options) {
|
return func(opts *Options) {
|
||||||
opts.Logger = logger
|
opts.Logger = logger
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/go-gost/gost/pkg/auth"
|
||||||
ssh_util "github.com/go-gost/gost/pkg/internal/util/ssh"
|
ssh_util "github.com/go-gost/gost/pkg/internal/util/ssh"
|
||||||
"github.com/go-gost/gost/pkg/listener"
|
"github.com/go-gost/gost/pkg/listener"
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
"github.com/go-gost/gost/pkg/logger"
|
||||||
@ -20,6 +21,7 @@ type sshListener struct {
|
|||||||
addr string
|
addr string
|
||||||
net.Listener
|
net.Listener
|
||||||
config *ssh.ServerConfig
|
config *ssh.ServerConfig
|
||||||
|
authenticator auth.Authenticator
|
||||||
cqueue chan net.Conn
|
cqueue chan net.Conn
|
||||||
errChan chan error
|
errChan chan error
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
@ -50,13 +52,13 @@ func (l *sshListener) Init(md md.Metadata) (err error) {
|
|||||||
l.Listener = ln
|
l.Listener = ln
|
||||||
|
|
||||||
config := &ssh.ServerConfig{
|
config := &ssh.ServerConfig{
|
||||||
PasswordCallback: ssh_util.PasswordCallback(l.md.authenticator),
|
PasswordCallback: ssh_util.PasswordCallback(l.authenticator),
|
||||||
PublicKeyCallback: ssh_util.PublicKeyCallback(l.md.authorizedKeys),
|
PublicKeyCallback: ssh_util.PublicKeyCallback(l.md.authorizedKeys),
|
||||||
}
|
}
|
||||||
|
|
||||||
config.AddHostKey(l.md.signer)
|
config.AddHostKey(l.md.signer)
|
||||||
|
|
||||||
if l.md.authenticator == nil && len(l.md.authorizedKeys) == 0 {
|
if l.authenticator == nil && len(l.md.authorizedKeys) == 0 {
|
||||||
config.NoClientAuth = true
|
config.NoClientAuth = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,9 +2,7 @@ package ssh
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/auth"
|
|
||||||
tls_util "github.com/go-gost/gost/pkg/common/util/tls"
|
tls_util "github.com/go-gost/gost/pkg/common/util/tls"
|
||||||
ssh_util "github.com/go-gost/gost/pkg/internal/util/ssh"
|
ssh_util "github.com/go-gost/gost/pkg/internal/util/ssh"
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
mdata "github.com/go-gost/gost/pkg/metadata"
|
||||||
@ -16,7 +14,6 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
authenticator auth.Authenticator
|
|
||||||
signer ssh.Signer
|
signer ssh.Signer
|
||||||
authorizedKeys map[string]bool
|
authorizedKeys map[string]bool
|
||||||
backlog int
|
backlog int
|
||||||
@ -24,26 +21,12 @@ type metadata struct {
|
|||||||
|
|
||||||
func (l *sshListener) parseMetadata(md mdata.Metadata) (err error) {
|
func (l *sshListener) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
const (
|
const (
|
||||||
users = "users"
|
|
||||||
authorizedKeys = "authorizedKeys"
|
authorizedKeys = "authorizedKeys"
|
||||||
privateKeyFile = "privateKeyFile"
|
privateKeyFile = "privateKeyFile"
|
||||||
passphrase = "passphrase"
|
passphrase = "passphrase"
|
||||||
backlog = "backlog"
|
backlog = "backlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
if auths := mdata.GetStrings(md, users); len(auths) > 0 {
|
|
||||||
authenticator := auth.NewLocalAuthenticator(nil)
|
|
||||||
for _, auth := range auths {
|
|
||||||
ss := strings.SplitN(auth, ":", 2)
|
|
||||||
if len(ss) == 1 {
|
|
||||||
authenticator.Add(ss[0], "")
|
|
||||||
} else {
|
|
||||||
authenticator.Add(ss[0], ss[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
l.md.authenticator = authenticator
|
|
||||||
}
|
|
||||||
|
|
||||||
if key := mdata.GetString(md, privateKeyFile); key != "" {
|
if key := mdata.GetString(md, privateKeyFile); key != "" {
|
||||||
data, err := ioutil.ReadFile(key)
|
data, err := ioutil.ReadFile(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Reference in New Issue
Block a user