Skip to content

Commit 15f0a66

Browse files
authored
[client] Allow ssh server on freebsd (#3170)
* Enable ssh server on freebsd * Fix listening in netstack mode * Fix panic if login cmd fails * Tidy up go mod
1 parent 9b5b632 commit 15f0a66

File tree

9 files changed

+60
-31
lines changed

9 files changed

+60
-31
lines changed

client/cmd/ssh.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"strings"
1010
"syscall"
1111

12-
log "github.com/sirupsen/logrus"
1312
"github.com/spf13/cobra"
1413

1514
"github.com/netbirdio/netbird/client/internal"
@@ -73,7 +72,7 @@ var sshCmd = &cobra.Command{
7372
go func() {
7473
// blocking
7574
if err := runSSH(sshctx, host, []byte(config.SSHKey), cmd); err != nil {
76-
log.Debug(err)
75+
cmd.Printf("Error: %v\n", err)
7776
os.Exit(1)
7877
}
7978
cancel()

client/internal/engine.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/netbirdio/netbird/client/iface"
2828
"github.com/netbirdio/netbird/client/iface/bind"
2929
"github.com/netbirdio/netbird/client/iface/device"
30+
"github.com/netbirdio/netbird/client/iface/netstack"
3031
"github.com/netbirdio/netbird/client/internal/acl"
3132
"github.com/netbirdio/netbird/client/internal/dns"
3233
"github.com/netbirdio/netbird/client/internal/dnsfwd"
@@ -699,18 +700,22 @@ func (e *Engine) updateSSH(sshConf *mgmProto.SSHConfig) error {
699700
} else {
700701

701702
if sshConf.GetSshEnabled() {
702-
if runtime.GOOS == "windows" || runtime.GOOS == "freebsd" {
703+
if runtime.GOOS == "windows" {
703704
log.Warnf("running SSH server on %s is not supported", runtime.GOOS)
704705
return nil
705706
}
706707
// start SSH server if it wasn't running
707708
if isNil(e.sshServer) {
709+
listenAddr := fmt.Sprintf("%s:%d", e.wgInterface.Address().IP.String(), nbssh.DefaultSSHPort)
710+
if netstack.IsEnabled() {
711+
listenAddr = fmt.Sprintf("127.0.0.1:%d", nbssh.DefaultSSHPort)
712+
}
708713
// nil sshServer means it has not yet been started
709714
var err error
710-
e.sshServer, err = e.sshServerFunc(e.config.SSHKey,
711-
fmt.Sprintf("%s:%d", e.wgInterface.Address().IP.String(), nbssh.DefaultSSHPort))
715+
e.sshServer, err = e.sshServerFunc(e.config.SSHKey, listenAddr)
716+
712717
if err != nil {
713-
return err
718+
return fmt.Errorf("create ssh server: %w", err)
714719
}
715720
go func() {
716721
// blocking
@@ -759,7 +764,7 @@ func (e *Engine) updateConfig(conf *mgmProto.PeerConfig) error {
759764
if conf.GetSshConfig() != nil {
760765
err := e.updateSSH(conf.GetSshConfig())
761766
if err != nil {
762-
log.Warnf("failed handling SSH server setup %v", err)
767+
log.Warnf("failed handling SSH server setup: %v", err)
763768
}
764769
}
765770

client/internal/engine_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ func TestMain(m *testing.M) {
7171
}
7272

7373
func TestEngine_SSH(t *testing.T) {
74-
// todo resolve test execution on freebsd
75-
if runtime.GOOS == "windows" || runtime.GOOS == "freebsd" {
74+
if runtime.GOOS == "windows" {
7675
t.Skip("skipping TestEngine_SSH")
7776
}
7877

client/ssh/login.go

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,29 @@ package ssh
22

33
import (
44
"fmt"
5-
"github.com/netbirdio/netbird/util"
65
"net"
76
"net/netip"
7+
"os"
88
"os/exec"
99
"runtime"
10+
11+
"github.com/netbirdio/netbird/util"
1012
)
1113

14+
func isRoot() bool {
15+
return os.Geteuid() == 0
16+
}
17+
1218
func getLoginCmd(user string, remoteAddr net.Addr) (loginPath string, args []string, err error) {
19+
if !isRoot() {
20+
shell := getUserShell(user)
21+
if shell == "" {
22+
shell = "/bin/sh"
23+
}
24+
25+
return shell, []string{"-l"}, nil
26+
}
27+
1328
loginPath, err = exec.LookPath("login")
1429
if err != nil {
1530
return "", nil, err
@@ -20,17 +35,17 @@ func getLoginCmd(user string, remoteAddr net.Addr) (loginPath string, args []str
2035
return "", nil, err
2136
}
2237

23-
if runtime.GOOS == "linux" {
24-
38+
switch runtime.GOOS {
39+
case "linux":
2540
if util.FileExists("/etc/arch-release") && !util.FileExists("/etc/pam.d/remote") {
26-
// detect if Arch Linux
2741
return loginPath, []string{"-f", user, "-p"}, nil
2842
}
29-
3043
return loginPath, []string{"-f", user, "-h", addrPort.Addr().String(), "-p"}, nil
31-
} else if runtime.GOOS == "darwin" {
44+
case "darwin":
3245
return loginPath, []string{"-fp", "-h", addrPort.Addr().String(), user}, nil
46+
case "freebsd":
47+
return loginPath, []string{"-f", user, "-h", addrPort.Addr().String(), "-p"}, nil
48+
default:
49+
return "", nil, fmt.Errorf("unsupported platform: %s", runtime.GOOS)
3350
}
34-
35-
return "", nil, fmt.Errorf("unsupported platform")
3651
}

client/ssh/lookup.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,9 @@ package ssh
66
import "os/user"
77

88
func userNameLookup(username string) (*user.User, error) {
9+
if username == "" || (username == "root" && !isRoot()) {
10+
return user.Current()
11+
}
12+
913
return user.Lookup(username)
1014
}

client/ssh/lookup_darwin.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ import (
1212
)
1313

1414
func userNameLookup(username string) (*user.User, error) {
15+
if username == "" || (username == "root" && !isRoot()) {
16+
return user.Current()
17+
}
18+
1519
var userObject *user.User
1620
userObject, err := user.Lookup(username)
1721
if err != nil && err.Error() == user.UnknownUserError(username).Error() {

client/ssh/server.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,12 @@ func (srv *DefaultServer) sessionHandler(session ssh.Session) {
168168
cmd := exec.Command(loginCmd, loginArgs...)
169169
go func() {
170170
<-session.Context().Done()
171+
if cmd.Process == nil {
172+
return
173+
}
171174
err := cmd.Process.Kill()
172175
if err != nil {
176+
log.Debugf("failed killing SSH process %v", err)
173177
return
174178
}
175179
}()
@@ -185,7 +189,7 @@ func (srv *DefaultServer) sessionHandler(session ssh.Session) {
185189
log.Debugf("Login command: %s", cmd.String())
186190
file, err := pty.Start(cmd)
187191
if err != nil {
188-
log.Errorf("failed starting SSH server %v", err)
192+
log.Errorf("failed starting SSH server: %v", err)
189193
}
190194

191195
go func() {

go.mod

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ require (
1919
github.com/spf13/cobra v1.7.0
2020
github.com/spf13/pflag v1.0.5
2121
github.com/vishvananda/netlink v1.2.1-beta.2
22-
golang.org/x/crypto v0.31.0
23-
golang.org/x/sys v0.28.0
22+
golang.org/x/crypto v0.32.0
23+
golang.org/x/sys v0.29.0
2424
golang.zx2c4.com/wireguard v0.0.0-20230704135630-469159ecf7d1
2525
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
2626
golang.zx2c4.com/wireguard/windows v0.5.3
@@ -41,7 +41,7 @@ require (
4141
github.com/davecgh/go-spew v1.1.1
4242
github.com/eko/gocache/v3 v3.1.1
4343
github.com/fsnotify/fsnotify v1.7.0
44-
github.com/gliderlabs/ssh v0.3.4
44+
github.com/gliderlabs/ssh v0.3.8
4545
github.com/godbus/dbus/v5 v5.1.0
4646
github.com/golang/mock v1.6.0
4747
github.com/google/go-cmp v0.6.0
@@ -94,7 +94,7 @@ require (
9494
golang.org/x/net v0.30.0
9595
golang.org/x/oauth2 v0.19.0
9696
golang.org/x/sync v0.10.0
97-
golang.org/x/term v0.27.0
97+
golang.org/x/term v0.28.0
9898
google.golang.org/api v0.177.0
9999
gopkg.in/yaml.v3 v3.0.1
100100
gorm.io/driver/mysql v1.5.7

go.sum

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2H
212212
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
213213
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
214214
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
215-
github.com/gliderlabs/ssh v0.3.4 h1:+AXBtim7MTKaLVPgvE+3mhewYRawNLTd+jEEz/wExZw=
216-
github.com/gliderlabs/ssh v0.3.4/go.mod h1:ZSS+CUoKHDrqVakTfTWUlKSr9MtMFkC4UvtQKD7O914=
215+
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
216+
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
217217
github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 h1:zDw5v7qm4yH7N8C8uWd+8Ii9rROdgWxQuGoJ9WDXxfk=
218218
github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw=
219219
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
@@ -776,14 +776,13 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
776776
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
777777
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
778778
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
779-
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
780779
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
781780
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
782781
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
783782
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
784783
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
785-
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
786-
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
784+
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
785+
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
787786
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
788787
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
789788
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -982,17 +981,17 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
982981
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
983982
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
984983
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
985-
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
986-
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
984+
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
985+
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
987986
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
988987
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
989988
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
990989
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
991990
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
992991
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
993992
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
994-
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
995-
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
993+
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
994+
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
996995
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
997996
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
998997
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

0 commit comments

Comments
 (0)