From c85c88efd67acd0689872c3d706c9b8b944c582a Mon Sep 17 00:00:00 2001 From: 9seconds Date: Fri, 30 Jul 2021 16:14:58 +0300 Subject: [PATCH] Add simple-run command --- internal/cli/access.go | 24 ++++----- internal/cli/cli.go | 3 +- internal/cli/generate_secret.go | 4 +- internal/cli/{proxy.go => run.go} | 6 +-- internal/cli/simple_run.go | 84 +++++++++++++++++++++++++++++++ mtglib/secret.go | 5 +- 6 files changed, 107 insertions(+), 19 deletions(-) rename internal/cli/{proxy.go => run.go} (73%) create mode 100644 internal/cli/simple_run.go diff --git a/internal/cli/access.go b/internal/cli/access.go index 6628269..23a47ce 100644 --- a/internal/cli/access.go +++ b/internal/cli/access.go @@ -44,8 +44,8 @@ type Access struct { Hex bool `kong:"help='Print secret in hex encoding.',short='x'"` } -func (c *Access) Run(cli *CLI, version string) error { - conf, err := utils.ReadConfig(c.ConfigPath) +func (a *Access) Run(cli *CLI, version string) error { + conf, err := utils.ReadConfig(a.ConfigPath) if err != nil { return fmt.Errorf("cannot init config: %w", err) } @@ -65,31 +65,31 @@ func (c *Access) Run(cli *CLI, version string) error { go func() { defer wg.Done() - ip := c.PublicIPv4 + ip := a.PublicIPv4 if ip == nil { - ip = c.getIP(ntw, "tcp4") + ip = a.getIP(ntw, "tcp4") } if ip != nil { ip = ip.To4() } - resp.IPv4 = c.makeURLs(conf, ip) + resp.IPv4 = a.makeURLs(conf, ip) }() go func() { defer wg.Done() - ip := c.PublicIPv6 + ip := a.PublicIPv6 if ip == nil { - ip = c.getIP(ntw, "tcp6") + ip = a.getIP(ntw, "tcp6") } if ip != nil { ip = ip.To16() } - resp.IPv6 = c.makeURLs(conf, ip) + resp.IPv6 = a.makeURLs(conf, ip) }() wg.Wait() @@ -105,7 +105,7 @@ func (c *Access) Run(cli *CLI, version string) error { return nil } -func (c *Access) getIP(ntw mtglib.Network, protocol string) net.IP { +func (a *Access) getIP(ntw mtglib.Network, protocol string) net.IP { client := ntw.MakeHTTPClient(func(ctx context.Context, network, address string) (net.Conn, error) { return ntw.DialContext(ctx, protocol, address) // nolint: wrapcheck }) @@ -139,12 +139,12 @@ func (c *Access) getIP(ntw mtglib.Network, protocol string) net.IP { return net.ParseIP(strings.TrimSpace(string(data))) } -func (c *Access) makeURLs(conf *config.Config, ip net.IP) *accessResponseURLs { +func (a *Access) makeURLs(conf *config.Config, ip net.IP) *accessResponseURLs { if ip == nil { return nil } - portNo := c.Port + portNo := a.Port if portNo == 0 { portNo = conf.BindTo.Port } @@ -153,7 +153,7 @@ func (c *Access) makeURLs(conf *config.Config, ip net.IP) *accessResponseURLs { values.Set("server", ip.String()) values.Set("port", strconv.Itoa(int(portNo))) - if c.Hex { + if a.Hex { values.Set("secret", conf.Secret.Hex()) } else { values.Set("secret", conf.Secret.Base64()) diff --git a/internal/cli/cli.go b/internal/cli/cli.go index d2d813c..f287ad8 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -5,6 +5,7 @@ import "github.com/alecthomas/kong" type CLI struct { GenerateSecret GenerateSecret `kong:"cmd,help='Generate new proxy secret'"` Access Access `kong:"cmd,help='Print access information.'"` - Run Proxy `kong:"cmd,help='Run proxy.'"` + Run Run `kong:"cmd,help='Run proxy.'"` + SimpleRun SimpleRun `kong:"cmd,help='Run proxy without config file.'"` Version kong.VersionFlag `kong:"help='Print version.',short='v'"` } diff --git a/internal/cli/generate_secret.go b/internal/cli/generate_secret.go index e3fb0e8..17b3b09 100644 --- a/internal/cli/generate_secret.go +++ b/internal/cli/generate_secret.go @@ -11,10 +11,10 @@ type GenerateSecret struct { Hex bool `kong:"help='Print secret in hex encoding.',short='x'"` } -func (c *GenerateSecret) Run(cli *CLI, _ string) error { +func (g *GenerateSecret) Run(cli *CLI, _ string) error { secret := mtglib.GenerateSecret(cli.GenerateSecret.HostName) - if cli.GenerateSecret.Hex { + if g.Hex { fmt.Println(secret.Hex()) // nolint: forbidigo } else { fmt.Println(secret.Base64()) // nolint: forbidigo diff --git a/internal/cli/proxy.go b/internal/cli/run.go similarity index 73% rename from internal/cli/proxy.go rename to internal/cli/run.go index 1990185..644f349 100644 --- a/internal/cli/proxy.go +++ b/internal/cli/run.go @@ -6,12 +6,12 @@ import ( "github.com/9seconds/mtg/v2/internal/utils" ) -type Proxy struct { +type Run struct { ConfigPath string `kong:"arg,required,type='existingfile',help='Path to the configuration file.',name='config-path'"` // nolint: lll } -func (c *Proxy) Run(cli *CLI, version string) error { - conf, err := utils.ReadConfig(c.ConfigPath) +func (r *Run) Run(cli *CLI, version string) error { + conf, err := utils.ReadConfig(r.ConfigPath) if err != nil { return fmt.Errorf("cannot init config: %w", err) } diff --git a/internal/cli/simple_run.go b/internal/cli/simple_run.go new file mode 100644 index 0000000..167b9c4 --- /dev/null +++ b/internal/cli/simple_run.go @@ -0,0 +1,84 @@ +package cli + +import ( + "fmt" + "net" + "strconv" + "time" + + "github.com/9seconds/mtg/v2/internal/config" +) + +type SimpleRun struct { + BindTo string `kong:"arg,required,name='bind-to',help='A host:port to bind proxy to.'"` + Secret string `kong:"arg,required,name='secret',help='Proxy secret.'"` + + Debug bool `kong:"name='debug',short='d',help='Run in debug mode.'"` + Concurrency uint64 `kong:"name='concurrency',short='c',default='8192',help='Max number of concurrent connection to proxy.'"` + TCPBuffer string `kong:"name='tcp-buffer',short='b',default='4KB',help='Size of TCP buffer to use.'"` + PreferIP string `kong:"name='prefer-ip',short='i',default='prefer-ipv6',help='IP preference. By default we prefer IPv6 with fallback to IPv4.'"` + DomainFrontingPort uint64 `kong:"name='domain-fronting-port',short='p',default='443',help='A port to access for domain fronting.'"` + DOHIP net.IP `kong:"name='doh-ip',short='d',default='9.9.9.9',help='IP address of DNS-over-HTTP to use.'"` + Timeout time.Duration `kong:"name='timeout',short='t',default='10s',help='Network timeout to use'"` + AntiReplayCacheSize string `kong:"name='antireplay-cache-size',short='a',default='1MB',help='A size of anti-replay cache to use.'"` +} + +func (s *SimpleRun) Run(cli *CLI, version string) error { + conf := &config.Config{} + + if err := conf.BindTo.Set(s.BindTo); err != nil { + return fmt.Errorf("incorrect bind-to parameter: %w", err) + } + + if err := conf.Secret.Set(s.Secret); err != nil { + return fmt.Errorf("incorrect secret: %w", err) + } + + if err := conf.Concurrency.Set(strconv.FormatUint(s.Concurrency, 10)); err != nil { + return fmt.Errorf("incorrect concurrency: %w", err) + } + + if err := conf.TCPBuffer.Set(s.TCPBuffer); err != nil { + return fmt.Errorf("incorrect tcp-buffer: %w", err) + } + + if err := conf.PreferIP.Set(s.PreferIP); err != nil { + return fmt.Errorf("incorrect prefer-ip: %w", err) + } + + if err := conf.DomainFrontingPort.Set(strconv.FormatUint(s.DomainFrontingPort, 10)); err != nil { + return fmt.Errorf("incorrect domain-fronting-port: %w", err) + } + + if err := conf.Network.DOHIP.Set(s.DOHIP.String()); err != nil { + return fmt.Errorf("incorrect doh-ip: %w", err) + } + + if err := conf.Network.Timeout.TCP.Set(s.Timeout.String()); err != nil { + return fmt.Errorf("incorrect timeout: %w", err) + } + + if err := conf.Network.Timeout.HTTP.Set(s.Timeout.String()); err != nil { + return fmt.Errorf("incorrect timeout: %w", err) + } + + if err := conf.Network.Timeout.Idle.Set(s.Timeout.String()); err != nil { + return fmt.Errorf("incorrect timeout: %w", err) + } + + if err := conf.Defense.AntiReplay.MaxSize.Set(s.AntiReplayCacheSize); err != nil { + return fmt.Errorf("incorrect antireplay-cache-size: %w", err) + } + + conf.Debug.Value = s.Debug + conf.Defense.AntiReplay.Enabled.Value = true + conf.Defense.Blocklist.Enabled.Value = false + conf.Stats.StatsD.Enabled.Value = false + conf.Stats.Prometheus.Enabled.Value = false + + if err := conf.Validate(); err != nil { + return fmt.Errorf("invalid result configuration: %w", err) + } + + return runProxy(conf, version) +} diff --git a/mtglib/secret.go b/mtglib/secret.go index 49fd106..eced181 100644 --- a/mtglib/secret.go +++ b/mtglib/secret.go @@ -58,7 +58,10 @@ func (s Secret) MarshalText() ([]byte, error) { // UnmarshalText is to support text.Unmarshaller interface. func (s *Secret) UnmarshalText(data []byte) error { - text := string(data) + return s.Set(string(data)) +} + +func (s *Secret) Set(text string) error { if text == "" { return ErrSecretEmpty }