Skip to content

Commit

Permalink
Merge pull request #153 from anywherelan/socks5-cli
Browse files Browse the repository at this point in the history
cli: display info for socks5 proxy, add commands `me list_proxies` and `me set_proxy`
  • Loading branch information
pymq authored Jan 12, 2025
2 parents 61cf441 + 91bfd0e commit 041145e
Show file tree
Hide file tree
Showing 11 changed files with 227 additions and 53 deletions.
6 changes: 4 additions & 2 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type Handler struct {
p2p *p2p.P2p
authStatus *service.AuthStatus
tunnel *service.Tunnel
socks5 *service.SOCKS5
dns DNSService
logBuffer *ringbuffer.RingBuffer

Expand All @@ -42,14 +43,15 @@ type Handler struct {
ctxCancel context.CancelFunc
}

func NewHandler(conf *config.Config, p2p *p2p.P2p, authStatus *service.AuthStatus,
tunnel *service.Tunnel, logBuffer *ringbuffer.RingBuffer, dns DNSService) *Handler {
func NewHandler(conf *config.Config, p2p *p2p.P2p, authStatus *service.AuthStatus, tunnel *service.Tunnel, socks5 *service.SOCKS5,
logBuffer *ringbuffer.RingBuffer, dns DNSService) *Handler {
ctx, ctxCancel := context.WithCancel(context.Background())
return &Handler{
conf: conf,
p2p: p2p,
authStatus: authStatus,
tunnel: tunnel,
socks5: socks5,
dns: dns,
logBuffer: logBuffer,
logger: log.Logger("awl/api"),
Expand Down
19 changes: 18 additions & 1 deletion api/apiclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import (
"net/url"
"time"

"github.com/google/go-querystring/query"

"github.com/anywherelan/awl/api"
"github.com/anywherelan/awl/config"
"github.com/anywherelan/awl/entity"
"github.com/google/go-querystring/query"
)

type Client struct {
Expand Down Expand Up @@ -57,6 +58,22 @@ func (c *Client) PeerInfo() (*entity.PeerInfo, error) {
return peerInfo, nil
}

func (c *Client) ListAvailableProxies() ([]entity.AvailableProxy, error) {
resp := entity.ListAvailableProxiesResponse{}
err := c.sendGetRequest(api.ListAvailableProxiesPath, &resp)
if err != nil {
return nil, err
}
return resp.Proxies, nil
}

func (c *Client) UpdateProxySettings(usingPeerID string) error {
request := entity.UpdateProxySettingsRequest{
UsingPeerID: usingPeerID,
}
return c.sendPostRequest(api.UpdateProxySettingsPath, request, nil)
}

func (c *Client) SendFriendRequest(peerID, alias string) error {
request := entity.FriendRequest{
PeerID: peerID,
Expand Down
15 changes: 1 addition & 14 deletions api/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,20 +94,7 @@ func (h *Handler) ExportServerConfiguration(c echo.Context) (err error) {
// @Success 200 {object} entity.ListAvailableProxiesResponse
// @Router /settings/list_proxies [GET]
func (h *Handler) ListAvailableProxies(c echo.Context) (err error) {
h.conf.RLock()
proxies := []entity.AvailableProxy{}
for _, peer := range h.conf.KnownPeers {
if !peer.AllowedUsingAsExitNode {
continue
}

proxy := entity.AvailableProxy{
PeerID: peer.PeerID,
PeerName: peer.DisplayName(),
}
proxies = append(proxies, proxy)
}
h.conf.RUnlock()
proxies := h.socks5.ListAvailableProxies()

response := entity.ListAvailableProxiesResponse{
Proxies: proxies,
Expand Down
2 changes: 1 addition & 1 deletion application.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func (a *Application) Init(ctx context.Context, tunDevice tun.Device) error {
a.Tunnel.RefreshPeersList()
}, a.Eventbus, new(awlevent.KnownPeerChanged))

handler := api.NewHandler(a.Conf, a.P2p, a.AuthStatus, a.Tunnel, a.LogBuffer, a.Dns)
handler := api.NewHandler(a.Conf, a.P2p, a.AuthStatus, a.Tunnel, a.SOCKS5, a.LogBuffer, a.Dns)
a.Api = handler
err = handler.SetupAPI()
if err != nil {
Expand Down
39 changes: 38 additions & 1 deletion application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,14 @@ func TestUpdateUseAsExitNodeConfig(t *testing.T) {
current := goleak.IgnoreCurrent()
goleak.VerifyNone(t, current)

info, err := peer1.api.PeerInfo()
ts.NoError(err)
ts.Equal("", info.SOCKS5.UsingPeerID)

availableProxies, err := peer1.api.ListAvailableProxies()
ts.NoError(err)
ts.Len(availableProxies, 0)

peer1Config, err := peer2.api.KnownPeerConfig(peer1.PeerID())
ts.NoError(err)
ts.Equal(false, peer1Config.AllowedUsingAsExitNode)
Expand All @@ -221,7 +229,13 @@ func TestUpdateUseAsExitNodeConfig(t *testing.T) {
return peer2Config.AllowedUsingAsExitNode
}, 15*time.Second, 100*time.Millisecond)

ts.Equal(peer2.PeerID(), peer1.app.Conf.SOCKS5.UsingPeerID)
info, err = peer1.api.PeerInfo()
ts.NoError(err)
ts.Equal(peer2.PeerID(), info.SOCKS5.UsingPeerID)

availableProxies, err = peer1.api.ListAvailableProxies()
ts.NoError(err)
ts.Len(availableProxies, 1)

// allow from peer1, check that peer2 got our config
err = peer1.api.UpdatePeerSettings(entity.UpdatePeerSettingsRequest{
Expand Down Expand Up @@ -258,13 +272,36 @@ func TestUpdateUseAsExitNodeConfig(t *testing.T) {
}, 15*time.Second, 100*time.Millisecond)

ts.Equal("", peer1.app.Conf.SOCKS5.UsingPeerID)

availableProxies, err = peer1.api.ListAvailableProxies()
ts.NoError(err)
ts.Len(availableProxies, 0)

testSOCKS5Proxy(ts, peer1.app.Conf.SOCKS5.ListenAddress, fmt.Sprintf("%s %s", "unknown error", "general SOCKS server failure"))

testSOCKS5Proxy(ts, peer2.app.Conf.SOCKS5.ListenAddress, fmt.Sprintf("%s %s", "unknown error", "connection not allowed by ruleset"))

peer1.app.SOCKS5.SetProxyingLocalhostEnabled(true)
testSOCKS5Proxy(ts, peer2.app.Conf.SOCKS5.ListenAddress, "")
peer1.app.SOCKS5.SetProxyingLocalhostEnabled(false)

// Testing API
err = peer1.api.UpdateProxySettings(peer2.PeerID())
ts.ErrorContains(err, "peer doesn't allow using as exit node")

err = peer2.api.UpdateProxySettings("asd")
ts.ErrorContains(err, "peer not found")

info, err = peer2.api.PeerInfo()
ts.NoError(err)
ts.Equal(peer1.PeerID(), info.SOCKS5.UsingPeerID)

err = peer2.api.UpdateProxySettings("")
ts.NoError(err)

info, err = peer2.api.PeerInfo()
ts.NoError(err)
ts.Equal("", info.SOCKS5.UsingPeerID)
}

func testSOCKS5Proxy(ts *TestSuite, proxyAddr string, expectSocksErr string) {
Expand Down
66 changes: 51 additions & 15 deletions cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ import (
"strings"

"github.com/GrigoryKrasnochub/updaterini"
"github.com/anywherelan/awl/api/apiclient"
"github.com/anywherelan/awl/config"
"github.com/anywherelan/awl/update"
"github.com/ipfs/go-log/v2"
"github.com/libp2p/go-libp2p/p2p/host/eventbus"
"github.com/urfave/cli/v2"

"github.com/anywherelan/awl/api/apiclient"
"github.com/anywherelan/awl/config"
"github.com/anywherelan/awl/update"
)

const (
Expand Down Expand Up @@ -86,10 +87,9 @@ func (a *Application) init() {
Usage: "Group of commands to work with your status and settings",
Subcommands: []*cli.Command{
{
Name: "status",
Aliases: []string{"stats"},
Usage: "Print your server status, network stats",
Before: a.initApiConnection,
Name: "status",
Usage: "Print your server status, network stats",
Before: a.initApiConnection,
Action: func(c *cli.Context) error {
return printStatus(a.api)
},
Expand Down Expand Up @@ -117,6 +117,36 @@ func (a *Application) init() {
return renameMe(a.api, c.String("name"))
},
},
{
Name: "list_proxies",
Usage: "Prints list of available SOCKS5 proxies",
Before: a.initApiConnection,
Action: func(c *cli.Context) error {
return listProxies(a.api)
},
},
{
Name: "set_proxy",
Usage: "Sets SOCKS5 proxy for your peer, empty pid/name means disable proxy",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "pid",
Usage: "peer id",
Required: false,
},
&cli.StringFlag{
Name: "name",
Usage: "peer name",
Required: false,
},
},
Before: func(c *cli.Context) error {
return a.initApiAndPeerId(c, false)
},
Action: func(c *cli.Context) error {
return setProxy(a.api, c.String("pid"))
},
},
},
},
{
Expand All @@ -131,10 +161,10 @@ func (a *Application) init() {
Name: "format",
Aliases: []string{"f"},
Required: false,
Value: "npslucv",
Value: "npslucev",
Usage: "control table columns list and order.Each char add column, write column chars together without gap. Use these chars to add specific columns:\n " +
"n - peers number\n p - peers name, domain and ip address\n i - peers id\n s - peers status\n l - peers last seen datetime\n v - peers awl version" +
"\n u - network usage by peer (in/out)\n c - list of peers connections (IP address + protocol)\n ",
"\n u - network usage by peer (in/out)\n c - list of peers connections (IP address + protocol)\n e - exit node status\n ",
},
},
Before: a.initApiConnection,
Expand Down Expand Up @@ -185,7 +215,7 @@ func (a *Application) init() {
Required: false,
},
},
Before: a.initApiAndPeerId,
Before: a.initApiAndPeerIdRequired,
Action: func(c *cli.Context) error {
return removePeer(a.api, c.String("pid"))
},
Expand All @@ -210,7 +240,7 @@ func (a *Application) init() {
Required: true,
},
},
Before: a.initApiAndPeerId,
Before: a.initApiAndPeerIdRequired,
Action: func(c *cli.Context) error {
return changePeerAlias(a.api, c.String("pid"), c.String("new_name"))
},
Expand All @@ -235,7 +265,7 @@ func (a *Application) init() {
Required: true,
},
},
Before: a.initApiAndPeerId,
Before: a.initApiAndPeerIdRequired,
Action: func(c *cli.Context) error {
return changePeerDomain(a.api, c.String("pid"), c.String("domain"))
},
Expand All @@ -260,7 +290,7 @@ func (a *Application) init() {
Required: false,
},
},
Before: a.initApiAndPeerId,
Before: a.initApiAndPeerIdRequired,
Action: func(c *cli.Context) error {
return setAllowUsingAsExitNode(a.api, c.String("pid"), c.Bool("allow"))
},
Expand Down Expand Up @@ -408,7 +438,11 @@ func (a *Application) initApiConnection(c *cli.Context) (err error) {
return nil
}

func (a *Application) initApiAndPeerId(c *cli.Context) error {
func (a *Application) initApiAndPeerIdRequired(c *cli.Context) error {
return a.initApiAndPeerId(c, true)
}

func (a *Application) initApiAndPeerId(c *cli.Context, isRequired bool) error {
err := a.initApiConnection(c)
if err != nil {
return err
Expand All @@ -419,8 +453,10 @@ func (a *Application) initApiAndPeerId(c *cli.Context) error {
return nil
}
alias := c.String("name")
if alias == "" {
if alias == "" && isRequired {
return fmt.Errorf("peerID or name should be defined")
} else if alias == "" && !isRequired {
return nil
}

pid, err = getPeerIdByAlias(a.api, alias)
Expand Down
50 changes: 43 additions & 7 deletions cli/me.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import (
"strings"
"time"

"github.com/anywherelan/awl/api/apiclient"
"github.com/mdp/qrterminal/v3"
"github.com/olekukonko/tablewriter"

"github.com/anywherelan/awl/api/apiclient"
)

func printStatus(api *apiclient.Client) error {
Expand All @@ -17,17 +18,15 @@ func printStatus(api *apiclient.Client) error {
return err
}

dnsStatus := "working"
if !stats.IsAwlDNSSetAsSystem {
dnsStatus = "not working"
}

table := tablewriter.NewWriter(os.Stdout)
table.AppendBulk([][]string{
{"Download rate", fmt.Sprintf("%s (%s)", stats.NetworkStatsInIECUnits.RateIn, stats.NetworkStatsInIECUnits.TotalIn)},
{"Upload rate", fmt.Sprintf("%s (%s)", stats.NetworkStatsInIECUnits.RateOut, stats.NetworkStatsInIECUnits.TotalOut)},
{"Bootstrap peers", fmt.Sprintf("%d/%d", stats.TotalBootstrapPeers, stats.ConnectedBootstrapPeers)},
{"DNS", dnsStatus},
{"DNS", formatWorkingStatus(stats.IsAwlDNSSetAsSystem)},
{"SOCKS5 Proxy", formatWorkingStatus(stats.SOCKS5.ListenerEnabled)},
{"SOCKS5 Proxy address", stats.SOCKS5.ListenAddress},
{"SOCKS5 Proxy exit node", stats.SOCKS5.UsingPeerName},
{"Reachability", strings.ToLower(stats.Reachability)},
{"Uptime", stats.Uptime.Round(time.Second).String()},
{"Server version", stats.ServerVersion},
Expand All @@ -38,6 +37,13 @@ func printStatus(api *apiclient.Client) error {
return nil
}

func formatWorkingStatus(working bool) string {
if working {
return "working"
}
return "not working"
}

func printPeerId(api *apiclient.Client) error {
info, err := api.PeerInfo()
if err != nil {
Expand All @@ -60,3 +66,33 @@ func renameMe(api *apiclient.Client, newName string) error {

return nil
}

func listProxies(api *apiclient.Client) error {
proxies, err := api.ListAvailableProxies()
if err != nil {
return err
}

if len(proxies) == 0 {
fmt.Println("no available proxies")
return nil
}

fmt.Println("Proxies:")
for _, proxy := range proxies {
fmt.Printf("- peer name: %s | peer id: %s\n", proxy.PeerName, proxy.PeerID)
}

return nil
}

func setProxy(api *apiclient.Client, peerID string) error {
err := api.UpdateProxySettings(peerID)
if err != nil {
return err
}

fmt.Println("proxy settings updated successfully")

return nil
}
Loading

0 comments on commit 041145e

Please sign in to comment.