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

Limit the Skychay UI to localhost #1605

Merged
merged 5 commits into from
Nov 2, 2023
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
19 changes: 16 additions & 3 deletions cmd/apps/skychat/skychat.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const (
port = routing.Port(1)
)

var addr = flag.String("addr", ":8001", "address to bind")
var addr = flag.String("addr", ":8001", "address to bind, put an * before the port if you want to be able to access outside localhost")
var r = netutil.NewRetrier(nil, 50*time.Millisecond, netutil.DefaultMaxBackoff, 5, 2)

var (
Expand Down Expand Up @@ -84,7 +84,20 @@ func main() {
http.HandleFunc("/message", messageHandler(ctx))
http.HandleFunc("/sse", sseHandler)

fmt.Println("Serving HTTP on", *addr)
url := ""
address := *addr
if len(address) < 5 || (address[:1] != ":" && address[:2] != "*:") {
url = "127.0.0.1:8001"
} else if address[:1] == ":" {
url = "127.0.0.1" + address
} else if address[:2] == "*:" {
url = address[1:]
} else {
url = "127.0.0.1:8001"
}

fmt.Println("Serving HTTP on", url)

if runtime.GOOS != "windows" {
termCh := make(chan os.Signal, 1)
signal.Notify(termCh, os.Interrupt)
Expand All @@ -97,7 +110,7 @@ func main() {
}
setAppStatus(appCl, appserver.AppDetailedStatusRunning)
srv := &http.Server{ //nolint gosec
Addr: *addr,
Addr: url,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
Expand Down
42 changes: 42 additions & 0 deletions pkg/visor/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"sync/atomic"
"time"
Expand Down Expand Up @@ -72,6 +73,7 @@ type API interface {
SetAppPassword(appName, password string) error
SetAppPK(appName string, pk cipher.PubKey) error
SetAppSecure(appName string, isSecure bool) error
SetAppAddress(appName string, address string) error
SetAppKillswitch(appName string, killswitch bool) error
SetAppNetworkInterface(appName string, netifc string) error
SetAppDNS(appName string, dnsaddr string) error
Expand Down Expand Up @@ -769,6 +771,46 @@ func (v *Visor) SetAppSecure(appName string, isSecure bool) error {
return nil
}

// SetAppAddress implements API.
func (v *Visor) SetAppAddress(appName string, address string) error {
// check app launcher availability
if v.appL == nil {
return ErrAppLauncherNotAvailable
}

if appName != visorconfig.SkychatName {
return fmt.Errorf("app %s is not allowed to set addr", appName)
}

if len(address) < 5 || (address[:1] != ":" && address[:2] != "*:") {
return fmt.Errorf("invalid addr value: %s", address)
}

forLocalhostOnly := address[:1] == ":"
prefix := 2
if forLocalhostOnly {
prefix = 1
}

portNumber, err := strconv.Atoi(address[prefix:])
if err != nil || portNumber < 1025 || portNumber > 65536 {
return fmt.Errorf("invalid port number: %s", strconv.Itoa(portNumber))
}

v.log.Infof("Setting %s addr to %v", appName, address)

const (
addrArg = "-addr"
)
if err := v.conf.UpdateAppArg(v.appL, appName, addrArg, address); err != nil {
return err
}

v.log.Infof("Updated %v addr state", appName)

return nil
}

// SetAppPK implements API.
func (v *Visor) SetAppPK(appName string, pk cipher.PubKey) error {
allowedToChangePK := func(appName string) bool {
Expand Down
10 changes: 9 additions & 1 deletion pkg/visor/hypervisor.go
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,7 @@ func (hv *Hypervisor) putApp() http.HandlerFunc {
AutoStart *bool `json:"autostart,omitempty"`
Killswitch *bool `json:"killswitch,omitempty"`
Secure *bool `json:"secure,omitempty"`
Address *string `json:"Address,omitempty"`
Status *int `json:"status,omitempty"`
Passcode *string `json:"passcode,omitempty"`
NetIfc *string `json:"netifc,omitempty"`
Expand All @@ -608,7 +609,7 @@ func (hv *Hypervisor) putApp() http.HandlerFunc {

shouldRestartApp := func(r req) bool {
// we restart the app if one of these fields was changed
return r.Killswitch != nil || r.Secure != nil || r.Passcode != nil ||
return r.Killswitch != nil || r.Secure != nil || r.Address != nil || r.Passcode != nil ||
r.PK != nil || r.NetIfc != nil || r.CustomSetting != nil
}

Expand Down Expand Up @@ -660,6 +661,13 @@ func (hv *Hypervisor) putApp() http.HandlerFunc {
}
}

if reqBody.Address != nil {
if err := ctx.API.SetAppAddress(ctx.App.Name, *reqBody.Address); err != nil {
httputil.WriteJSON(w, r, http.StatusInternalServerError, err)
return
}
}

if reqBody.NetIfc != nil {
if err := ctx.API.SetAppNetworkInterface(ctx.App.Name, *reqBody.NetIfc); err != nil {
httputil.WriteJSON(w, r, http.StatusInternalServerError, err)
Expand Down
7 changes: 7 additions & 0 deletions pkg/visor/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,13 @@ func (r *RPC) SetAppSecure(in *SetAppBoolIn, _ *struct{}) (err error) {
return r.visor.SetAppSecure(in.AppName, in.Val)
}

// SetAppAddress sets addr flag for the app
func (r *RPC) SetAppAddress(in *SetAppStringIn, _ *struct{}) (err error) {
defer rpcutil.LogCall(r.log, "SetAppAddress", in)(nil, &err)

return r.visor.SetAppAddress(in.AppName, in.Val)
}

// GetAppStats gets app runtime statistics.
func (r *RPC) GetAppStats(appName *string, out *appserver.AppStats) (err error) {
defer rpcutil.LogCall(r.log, "GetAppStats", appName)(out, &err)
Expand Down
23 changes: 23 additions & 0 deletions pkg/visor/rpc_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,14 @@ func (rc *rpcClient) SetAppSecure(appName string, isSecure bool) error {
}, &struct{}{})
}

// SetAppAddress implements API.
func (rc *rpcClient) SetAppAddress(appName string, address string) error {
return rc.Call("SetAppAddress", &SetAppStringIn{
AppName: appName,
Val: address,
}, &struct{}{})
}

// SetAppDNS implements API.
func (rc *rpcClient) SetAppDNS(appName string, dnsAddr string) error {
return rc.Call("SetAppDNS", &SetAppStringIn{
Expand Down Expand Up @@ -980,6 +988,21 @@ func (mc *mockRPCClient) SetAppSecure(appName string, isSecure bool) error { //n
})
}

// SetAppAddress implements API.
func (mc *mockRPCClient) SetAppAddress(appName string, address string) error { //nolint:all
return mc.do(true, func() error {
const chatName = "skychat"

for i := range mc.o.Apps {
if mc.o.Apps[i].Name == chatName {
return nil
}
}

return fmt.Errorf("app of name '%s' does not exist", chatName)
})
}

// SetAppDNS implements API.
func (mc *mockRPCClient) SetAppDNS(string, string) error {
return mc.do(true, func() error {
Expand Down
2 changes: 2 additions & 0 deletions static/skywire-manager-src/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ import { RewardsAddressComponent } from './components/pages/node/node-info/node-
import { BulkRewardAddressChangerComponent } from './components/layout/bulk-reward-address-changer/bulk-reward-address-changer.component';
import { UserAppSettingsComponent } from './components/pages/node/apps/node-apps/user-app-settings/user-app-settings.component';
import { NodeLogsComponent } from './components/pages/node/actions/node-logs/node-logs.component';
import { SkychatSettingsComponent } from './components/pages/node/apps/node-apps/skychat-settings/skychat-settings.component';
import { TabSelectorComponent } from './components/layout/tab-selector/tab-selector.component';

const globalRippleConfig: RippleGlobalOptions = {
Expand Down Expand Up @@ -179,6 +180,7 @@ const globalRippleConfig: RippleGlobalOptions = {
BulkRewardAddressChangerComponent,
UserAppSettingsComponent,
NodeLogsComponent,
SkychatSettingsComponent,
TabSelectorComponent,
],
imports: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { FilterProperties, FilterFieldTypes } from 'src/app/utils/filters';
import { SortingColumn, SortingModes, DataSorter } from 'src/app/utils/lists/data-sorter';
import { DataFilterer } from 'src/app/utils/lists/data-filterer';
import { UserAppSettingsComponent } from '../node-apps/user-app-settings/user-app-settings.component';
import { SkychatSettingsComponent } from '../node-apps/skychat-settings/skychat-settings.component';

/**
* Shows the list of applications of a node. It shows official or user apps, not both at the
Expand Down Expand Up @@ -80,7 +81,7 @@ export class NodeAppsListComponent implements OnInit, OnDestroy {
}

// List with the names of all the apps which can not be configured directly on the manager.
appsWithoutConfig = new Set<string>(['skychat']);
appsWithoutConfig = new Set<string>();

// All apps the ode has.
allApps: Application[];
Expand Down Expand Up @@ -248,14 +249,23 @@ export class NodeAppsListComponent implements OnInit, OnDestroy {
*/
getLink(app: Application): string {
if (app.name.toLocaleLowerCase() === 'skychat' && this.nodeIp && app.status !== 0 && app.status !== 2) {
// Default port.
// Default port and ip.
let port = '8001';
let url = '127.0.0.1';

// Try to get the port from the config array.
// Try to get the address and port from the config array.
if (app.args) {
for (let i = 0; i < app.args.length; i++) {
if (app.args[i] === '-addr' && i + 1 < app.args.length) {
port = (app.args[i + 1] as string).trim();
const addr = (app.args[i + 1] as string).trim();

const parts = addr.split(':');
// If the app can be accessed outside localhost, use the remote ip.
if (parts[0] === '*') {
url = this.nodeIp;
}

port = parts[1];
}
}
}
Expand All @@ -264,7 +274,7 @@ export class NodeAppsListComponent implements OnInit, OnDestroy {
port = ':' + port;
}

return 'http://' + this.nodeIp + port;
return 'http://' + url + port;
} else if (app.name.toLocaleLowerCase() === 'vpn-client' && this.nodePK) {
return location.origin + '/#/vpn/' + this.nodePK + '/status';
} else if (!this.officialAppsList.has(app.name)) {
Expand Down Expand Up @@ -574,12 +584,12 @@ export class NodeAppsListComponent implements OnInit, OnDestroy {
* Shows the appropriate modal window for configuring the app.
*/
config(app: Application): void {
if (app.name === 'skysocks' || app.name === 'vpn-server') {
if (app.name === 'skychat') {
SkychatSettingsComponent.openDialog(this.dialog, app);
} else if (app.name === 'skysocks' || app.name === 'vpn-server') {
SkysocksSettingsComponent.openDialog(this.dialog, app);
} else if (app.name === 'skysocks-client' || app.name === 'vpn-client') {
SkysocksClientSettingsComponent.openDialog(this.dialog, app);
} else if (app.name === 'skychat') {
this.snackbarService.showError('apps.error');
} else {
UserAppSettingsComponent.openDialog(this.dialog, app);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<app-dialog
[headline]="('apps.skychat-settings.title') | translate"
[dialog]="dialogRef"
[disableDismiss]="disableDismiss"
>
<form [formGroup]="form">

<mat-form-field [ngClass]="{'element-disabled' : disableDismiss}">
<div class="field-container">
<label class="field-label" for="localhostOnly">{{ 'apps.skychat-settings.localhost-only' | translate }}</label>
<mat-select formControlName="localhostOnly">
<mat-option [value]="true">{{ 'common.yes' | translate }}</mat-option>
<mat-option [value]="false">{{ 'common.no' | translate }}</mat-option>
</mat-select>
</div>
</mat-form-field>

<mat-form-field [ngClass]="{'element-disabled' : disableDismiss}">
<div class="field-container">
<label class="field-label" for="port">{{ 'apps.skychat-settings.port' | translate }}</label>
<input
formControlName="port"
type="number"
matInput
>
</div>
<mat-error>
<span>{{ 'apps.skychat-settings.port-error' | translate }}</span>
</mat-error>
</mat-form-field>
</form>

<app-button
#button
(action)="saveChanges()"
[disabled]="!form.valid"
color="primary"
class="float-right"
>
{{ 'apps.skychat-settings.save' | translate }}
</app-button>
</app-dialog>
Loading
Loading