Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into stable
Browse files Browse the repository at this point in the history
  • Loading branch information
9seconds committed Jul 31, 2021
2 parents 0c5d487 + 6cd9160 commit 8758208
Show file tree
Hide file tree
Showing 77 changed files with 2,015 additions and 2,087 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ jobs:
- name: Run linter
uses: golangci/golangci-lint-action@v2
with:
version: v1.39.0
version: v1.41.1

docker:
name: Docker
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
IMAGE_NAME := mtg
APP_NAME := $(IMAGE_NAME)

GOLANGCI_LINT_VERSION := v1.39.0
GOLANGCI_LINT_VERSION := v1.41.1

VERSION_GO := $(shell go version)
VERSION_DATE := $(shell date -Ru)
Expand Down
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,50 @@ For example, you've bought a VPS from [Digital
Ocean](https://www.digitalocean.com/). Then it might be a good idea to
generate a secret for _digitalocean.com_ then.


### Simple run mode

mtg supports 2 modes: simple and normal. Simple mode allows starting
proxy with a small subset of configuration options you usually want to
modify. This is quite good for oneliners that you can copy-paste and do
not bother about external files whatsoever.

Let's take a look:

```console
Usage: mtg simple-run <bind-to> <secret>

Run proxy without config file.

Arguments:
<bind-to> A host:port to bind proxy to.
<secret> Proxy secret.

Flags:
-h, --help Show context-sensitive help.
-v, --version Print version.

-d, --debug Run in debug mode.
-c, --concurrency=8192 Max number of concurrent connection to proxy.
-b, --tcp-buffer="4KB" Size of TCP buffer to use.
-i, --prefer-ip="prefer-ipv6" IP preference. By default we prefer IPv6 with fallback to IPv4.
-p, --domain-fronting-port=443 A port to access for domain fronting.
-n, --doh-ip=9.9.9.9 IP address of DNS-over-HTTP to use.
-t, --timeout=10s Network timeout to use
-a, --antireplay-cache-size="1MB" A size of anti-replay cache to use.
```

So, if you want to startup a proxy with CLI only, you can do something like

```console
$ mtg simple-run -n 1.1.1.1 -t 30s -a 512kib 127.0.0.1:3128 7hBO-dCS4EBzenlKbdLFxyNnb29nbGUuY29t
```

The rest of the configuration will be taken from default values. But
a simple run is fine if you do not have any special requirements or
granular tuning. If you want it, please checkout the configuration
files.

### Prepare a configuration file

Please checkout an example configuration file. All options except of
Expand Down
21 changes: 11 additions & 10 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.16

require (
github.com/OneOfOne/xxhash v1.2.8
github.com/alecthomas/kong v0.2.16
github.com/alecthomas/kong v0.2.17
github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6
Expand All @@ -15,17 +15,18 @@ require (
github.com/kentik/patricia v0.0.0-20201202224819-f9447a6e25f1
github.com/libp2p/go-reuseport v0.0.2
github.com/mccutchen/go-httpbin v1.1.1
github.com/panjf2000/ants/v2 v2.4.4
github.com/pelletier/go-toml v1.9.1
github.com/prometheus/client_golang v1.10.0
github.com/prometheus/common v0.24.0 // indirect
github.com/rs/zerolog v1.22.0
github.com/panjf2000/ants/v2 v2.4.6
github.com/pelletier/go-toml v1.9.3
github.com/prometheus/client_golang v1.11.0
github.com/prometheus/common v0.30.0 // indirect
github.com/prometheus/procfs v0.7.1 // indirect
github.com/rs/zerolog v1.23.0
github.com/smira/go-statsd v1.3.2
github.com/stretchr/objx v0.3.0 // indirect
github.com/stretchr/testify v1.7.0
github.com/tylertreat/BoomFilters v0.0.0-20210315201527-1a82519a3e43
github.com/xeipuuv/gojsonschema v1.2.0
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a
golang.org/x/net v0.0.0-20210510120150-4163338589ed
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c
google.golang.org/protobuf v1.27.1 // indirect
)
510 changes: 274 additions & 236 deletions go.sum

Large diffs are not rendered by default.

81 changes: 36 additions & 45 deletions internal/cli/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import (
"strconv"
"strings"
"sync"

"github.com/9seconds/mtg/v2/internal/config"
"github.com/9seconds/mtg/v2/internal/utils"
"github.com/9seconds/mtg/v2/mtglib"
)

type accessResponse struct {
Expand All @@ -26,65 +30,66 @@ type accessResponse struct {
type accessResponseURLs struct {
IP net.IP `json:"ip"`
Port uint `json:"port"`
TgURL string `json:"tg_url"`
TgQrCode string `json:"tg_qrcode"`
TmeURL string `json:"tme_url"`
TmeQrCode string `json:"tme_qrcode"`
TgURL string `json:"tg_url"` // nolint: tagliatelle
TgQrCode string `json:"tg_qrcode"` // nolint: tagliatelle
TmeURL string `json:"tme_url"` // nolint: tagliatelle
TmeQrCode string `json:"tme_qrcode"` // nolint: tagliatelle
}

type Access struct {
base

ConfigPath string `kong:"arg,required,type='existingfile',help='Path to the configuration file.',name='config-path'"` // nolint: lll
PublicIPv4 net.IP `kong:"help='Public IPv4 address for proxy. By default it is resolved via remote website',name='ipv4',short='i'"` // nolint: lll
PublicIPv6 net.IP `kong:"help='Public IPv6 address for proxy. By default it is resolved via remote website',name='ipv6',short='I'"` // nolint: lll
Port uint `kong:"help='Port number. Default port is taken from configuration file, bind-to parameter',type:'uint',short='p'"` // nolint: lll
Hex bool `kong:"help='Print secret in hex encoding.',short='x'"`
}

func (c *Access) Run(cli *CLI, version string) error {
if err := c.ReadConfig(version); err != nil {
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)
}

return c.Execute(cli)
}

func (c *Access) Execute(cli *CLI) error {
resp := &accessResponse{}
resp.Secret.Base64 = c.Config.Secret.Base64()
resp.Secret.Hex = c.Config.Secret.Hex()
resp.Secret.Base64 = conf.Secret.Base64()
resp.Secret.Hex = conf.Secret.Hex()

ntw, err := makeNetwork(conf, version)
if err != nil {
return fmt.Errorf("cannot init network: %w", err)
}

wg := &sync.WaitGroup{}
wg.Add(2) // nolint: gomnd

go func() {
defer wg.Done()

ip := cli.Access.PublicIPv4
ip := a.PublicIPv4
if ip == nil {
ip = c.getIP("tcp4")
ip = a.getIP(ntw, "tcp4")
}

if ip != nil {
ip = ip.To4()
}

resp.IPv4 = c.makeURLs(ip, cli)
resp.IPv4 = a.makeURLs(conf, ip)
}()

go func() {
defer wg.Done()

ip := cli.Access.PublicIPv6
ip := a.PublicIPv6
if ip == nil {
ip = c.getIP("tcp6")
ip = a.getIP(ntw, "tcp6")
}

if ip != nil {
ip = ip.To16()
}

resp.IPv6 = c.makeURLs(ip, cli)
resp.IPv6 = a.makeURLs(conf, ip)
}()

wg.Wait()
Expand All @@ -100,9 +105,9 @@ func (c *Access) Execute(cli *CLI) error {
return nil
}

func (c *Access) getIP(protocol string) net.IP {
client := c.Network.MakeHTTPClient(func(ctx context.Context, network, address string) (net.Conn, error) {
return c.Network.DialContext(ctx, protocol, address) // nolint: wrapcheck
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
})

req, err := http.NewRequest(http.MethodGet, "https://ifconfig.co", nil) // nolint: noctx
Expand Down Expand Up @@ -134,24 +139,24 @@ func (c *Access) getIP(protocol string) net.IP {
return net.ParseIP(strings.TrimSpace(string(data)))
}

func (c *Access) makeURLs(ip net.IP, cli *CLI) *accessResponseURLs {
func (a *Access) makeURLs(conf *config.Config, ip net.IP) *accessResponseURLs {
if ip == nil {
return nil
}

portNo := cli.Access.Port
portNo := a.Port
if portNo == 0 {
portNo = c.Config.BindTo.PortValue(0)
portNo = conf.BindTo.Port
}

values := url.Values{}
values.Set("server", ip.String())
values.Set("port", strconv.Itoa(int(portNo)))

if cli.Access.Hex {
values.Set("secret", c.Config.Secret.Hex())
if a.Hex {
values.Set("secret", conf.Secret.Hex())
} else {
values.Set("secret", c.Config.Secret.Base64())
values.Set("secret", conf.Secret.Base64())
}

urlQuery := values.Encode()
Expand All @@ -171,22 +176,8 @@ func (c *Access) makeURLs(ip net.IP, cli *CLI) *accessResponseURLs {
RawQuery: urlQuery,
}).String(),
}
rv.TgQrCode = c.makeQRCode(rv.TgURL)
rv.TmeQrCode = c.makeQRCode(rv.TmeURL)
rv.TgQrCode = utils.MakeQRCodeURL(rv.TgURL)
rv.TmeQrCode = utils.MakeQRCodeURL(rv.TmeURL)

return rv
}

func (c *Access) makeQRCode(data string) string {
values := url.Values{}
values.Set("qzone", "4")
values.Set("format", "svg")
values.Set("data", data)

return (&url.URL{
Scheme: "https",
Host: "api.qrserver.com",
Path: "v1/create-qr-code",
RawQuery: values.Encode(),
}).String()
}
Loading

0 comments on commit 8758208

Please sign in to comment.