Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cli: display info for socks5 proxy, add commands me list_proxies and me set_proxy #153

Merged
merged 3 commits into from
Jan 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading