update config
This commit is contained in:
171
cmd/gost/cmd.go
171
cmd/gost/cmd.go
@ -7,11 +7,12 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/go-gost/gost/pkg/config"
|
||||
"github.com/go-gost/gost/pkg/registry"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidService = errors.New("invalid service")
|
||||
ErrInvalidNode = errors.New("invalid node")
|
||||
ErrInvalidCmd = errors.New("invalid cmd")
|
||||
ErrInvalidNode = errors.New("invalid node")
|
||||
)
|
||||
|
||||
type stringList []string
|
||||
@ -36,32 +37,36 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
|
||||
}
|
||||
|
||||
for i, node := range nodes {
|
||||
url, err := checkCmd(node)
|
||||
url, err := normCmd(node)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodeConfig, err := buildNodeConfig(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nodeConfig.Name = "node-0"
|
||||
|
||||
chain.Hops = append(chain.Hops, &config.HopConfig{
|
||||
Name: fmt.Sprintf("hop-%d", i),
|
||||
Nodes: []*config.NodeConfig{
|
||||
{
|
||||
Name: "node-0",
|
||||
URL: url,
|
||||
},
|
||||
},
|
||||
Name: fmt.Sprintf("hop-%d", i),
|
||||
Nodes: []*config.NodeConfig{nodeConfig},
|
||||
})
|
||||
}
|
||||
|
||||
for i, svc := range services {
|
||||
url, err := checkCmd(svc)
|
||||
url, err := normCmd(svc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
service := &config.ServiceConfig{
|
||||
Name: fmt.Sprintf("service-%d", i),
|
||||
URL: url,
|
||||
|
||||
service, err := buildServiceConfig(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
service.Name = fmt.Sprintf("service-%d", i)
|
||||
if chain != nil {
|
||||
service.Chain = chain.Name
|
||||
service.Handler.Chain = chain.Name
|
||||
}
|
||||
cfg.Services = append(cfg.Services, service)
|
||||
}
|
||||
@ -69,20 +74,140 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
|
||||
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)
|
||||
if s == "" {
|
||||
return "", ErrInvalidService
|
||||
return nil, ErrInvalidCmd
|
||||
}
|
||||
|
||||
if !strings.Contains(s, "://") {
|
||||
s = "auto://" + s
|
||||
}
|
||||
|
||||
u, err := url.Parse(s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return u.String(), nil
|
||||
return url.Parse(s)
|
||||
}
|
||||
|
@ -3,9 +3,11 @@ package main
|
||||
import (
|
||||
"io"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"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"
|
||||
@ -54,12 +56,14 @@ func buildService(cfg *config.Config) (services []*service.Service) {
|
||||
}
|
||||
|
||||
for _, svc := range cfg.Services {
|
||||
if svc.Listener == nil || svc.Handler == nil {
|
||||
continue
|
||||
}
|
||||
serviceLogger := log.WithFields(map[string]interface{}{
|
||||
"kind": "service",
|
||||
"service": svc.Name,
|
||||
"listener": svc.Listener.Type,
|
||||
"handler": svc.Handler.Type,
|
||||
"chain": svc.Chain,
|
||||
})
|
||||
|
||||
listenerLogger := serviceLogger.WithFields(map[string]interface{}{
|
||||
@ -67,11 +71,12 @@ func buildService(cfg *config.Config) (services []*service.Service) {
|
||||
})
|
||||
ln := registry.GetListener(svc.Listener.Type)(
|
||||
listener.AddrOption(svc.Addr),
|
||||
listener.AuthenticatorOption(authFromConfig(svc.Listener.Auths...)),
|
||||
listener.LoggerOption(listenerLogger),
|
||||
)
|
||||
|
||||
if chainable, ok := ln.(chain.Chainable); ok {
|
||||
chainable.WithChain(chains[svc.Chain])
|
||||
chainable.WithChain(chains[svc.Listener.Chain])
|
||||
}
|
||||
|
||||
if svc.Listener.Metadata == nil {
|
||||
@ -86,12 +91,13 @@ func buildService(cfg *config.Config) (services []*service.Service) {
|
||||
})
|
||||
|
||||
h := registry.GetHandler(svc.Handler.Type)(
|
||||
handler.BypassOption(bypasses[svc.Bypass]),
|
||||
handler.LoggerOption(handlerLogger),
|
||||
handler.BypassOption(bypasses[svc.Handler.Bypass]),
|
||||
handler.AuthenticatorOption(authFromConfig(svc.Handler.Auths...)),
|
||||
handler.RouterOption(&chain.Router{
|
||||
Chain: chains[svc.Chain],
|
||||
Resolver: resolvers[svc.Resolver],
|
||||
Hosts: hosts[svc.Hosts],
|
||||
Chain: chains[svc.Handler.Chain],
|
||||
Resolver: resolvers[svc.Handler.Resolver],
|
||||
Hosts: hosts[svc.Handler.Hosts],
|
||||
Logger: handlerLogger,
|
||||
}),
|
||||
)
|
||||
@ -134,14 +140,27 @@ func chainFromConfig(cfg *config.ChainConfig) *chain.Chain {
|
||||
for _, hop := range cfg.Hops {
|
||||
group := &chain.NodeGroup{}
|
||||
for _, v := range hop.Nodes {
|
||||
connectorLogger := chainLogger.WithFields(map[string]interface{}{
|
||||
"kind": "connector",
|
||||
nodeLogger := chainLogger.WithFields(map[string]interface{}{
|
||||
"kind": "node",
|
||||
"connector": v.Connector.Type,
|
||||
"dialer": v.Dialer.Type,
|
||||
"hop": hop.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)(
|
||||
connector.UserOption(connectorUser),
|
||||
connector.LoggerOption(connectorLogger),
|
||||
)
|
||||
|
||||
@ -152,14 +171,20 @@ func chainFromConfig(cfg *config.ChainConfig) *chain.Chain {
|
||||
connectorLogger.Fatal("init: ", err)
|
||||
}
|
||||
|
||||
dialerLogger := chainLogger.WithFields(map[string]interface{}{
|
||||
"kind": "dialer",
|
||||
"connector": v.Connector.Type,
|
||||
"dialer": v.Dialer.Type,
|
||||
"hop": hop.Name,
|
||||
"node": v.Name,
|
||||
dialerLogger := nodeLogger.WithFields(map[string]interface{}{
|
||||
"kind": "dialer",
|
||||
})
|
||||
|
||||
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)(
|
||||
dialer.UserOption(dialerUser),
|
||||
dialer.LoggerOption(dialerLogger),
|
||||
)
|
||||
|
||||
@ -305,3 +330,18 @@ func hostsFromConfig(cfg *config.HostsConfig) hostspkg.HostMapper {
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
normConfig(cfg)
|
||||
|
||||
log = logFromConfig(cfg.Log)
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user