Skip to content

[client] Rewrite the SSH feature #4015

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

Open
wants to merge 52 commits into
base: main
Choose a base branch
from
Open

[client] Rewrite the SSH feature #4015

wants to merge 52 commits into from

Conversation

lixmal
Copy link
Collaborator

@lixmal lixmal commented Jun 19, 2025

Describe your changes

NetBird SSH Client

  • Port forwarding
  • Windows support
  • Non-interactive commands
  • Single command execution over SSH

SSH Server

  • SFTP
  • Port forwarding (without user switching)
  • PTY (interactive, non-interactive)
  • Non-PTY (commands)
  • Windows support

New Flags

--enable-ssh-local-port-forwarding
--enable-ssh-remote-port-forwarding
--enable-ssh-root
--enable-ssh-sftp

Changes

  • Default port changed to 22022
  • Redirect port 22 to 22022 when SSH server enabled
  • Remove implicit OpenSSH firewall port
  • Native SSH clients: known_hosts setup with peer IPs and hostnames

Issue ticket number and link

Stack

Checklist

  • Is it a bug fix
  • Is a typo/documentation fix
  • Is a feature enhancement
  • It is a refactor
  • Created tests that fail without the change (if possible)
  • Extended the README / documentation, if necessary

By submitting this pull request, you confirm that you have read and agree to the terms of the Contributor License Agreement.

@lixmal lixmal marked this pull request as ready for review June 20, 2025 15:25
@Copilot Copilot AI review requested due to automatic review settings June 20, 2025 15:25
Copilot

This comment was marked as outdated.

@lixmal lixmal marked this pull request as draft June 22, 2025 14:49
@lixmal lixmal marked this pull request as ready for review July 3, 2025 14:17
@lixmal lixmal requested review from pappz and Copilot July 3, 2025 14:17
Copilot

This comment was marked as outdated.

@lixmal lixmal requested a review from Copilot July 4, 2025 09:05
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR overhauls the SSH feature by extending the management API with new SSH flags, updating dependencies for SFTP support, and refactoring the client UI into a tabbed settings interface that includes SSH options.

  • Added enableSSHRoot, enableSSHSFTP, enableSSHLocalPortForwarding, and enableSSHRemotePortForwarding flags to management.proto.
  • Bumped Go module dependencies (including github.com/pkg/sftp) in go.mod.
  • Refactored client/ui/client_ui.go to use a tabbed settings form and integrated SSH settings.
  • Removed platform-specific setWinSize stubs in client/ssh.

Reviewed Changes

Copilot reviewed 77 out of 79 changed files in this pull request and generated no comments.

Show a summary per file
File Description
management/proto/management.proto Added four new SSH-related boolean flags
go.mod Updated dependency versions and added SFTP package
client/ui/client_ui.go Refactored settings UI into tabs and added SSH form
client/ssh/window_windows.go Removed Windows PTY resize stub
client/ssh/window_unix.go Removed Unix PTY resize stub
client/ssh/window_freebsd.go Removed FreeBSD PTY resize stub
Comments suppressed due to low confidence (3)

go.mod:195

  • The github.com/kr/fs dependency is added but not referenced in the changes; consider removing this unused indirect dependency to keep the module clean.
	github.com/kr/fs v0.1.0 // indirect

client/ui/client_ui.go:377

  • [nitpick] The settings window height was reduced from 500 to 400, which may truncate the SSH tab content. Verify the new layout and adjust the window size as needed to prevent clipping.
	s.wSettings.Resize(fyne.NewSize(600, 400))

Base automatically changed from android-dns-routes to main July 4, 2025 14:43
@pappz
Copy link
Contributor

pappz commented Jul 8, 2025

Why do we have multiple lines?

root@ubuntu2:/etc/ssh/ssh_known_hosts.d# cat 99-netbird 
# NetBird SSH known hosts
# Generated automatically - do not edit manually

100.108.5.104,ubuntu1.netbird.selfhosted,ubuntu1,[100.108.5.104]:22,[100.108.5.104]:22022 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBt+HdgXSos2HtJP74gwd5M+lNwrLkbaLhQmRl23/AAg
100.108.5.104,ubuntu1.netbird.selfhosted,ubuntu1,[100.108.5.104]:22,[100.108.5.104]:22022 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBt+HdgXSos2HtJP74gwd5M+lNwrLkbaLhQmRl23/AAg
100.108.5.104,ubuntu1.netbird.selfhosted,ubuntu1,[100.108.5.104]:22,[100.108.5.104]:22022 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBt+HdgXSos2HtJP74gwd5M+lNwrLkbaLhQmRl23/AAg
100.108.5.104,ubuntu1.netbird.selfhosted,ubuntu1,[100.108.5.104]:22,[100.108.5.104]:22022 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBt+HdgXSos2HtJP74gwd5M+lNwrLkbaLhQmRl23/AAg
100.108.5.104,ubuntu1.netbird.selfhosted,ubuntu1,[100.108.5.104]:22,[100.108.5.104]:22022 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBt+HdgXSos2HtJP74gwd5M+lNwrLkbaLhQmRl23/AAg
root@ubuntu2:/etc/ssh/ssh_known_hosts.d# 

@pappz
Copy link
Contributor

pappz commented Jul 8, 2025

What is the proper way to disable this feature and start using the original sshd configuration?

func (s *Server) SetAllowRemotePortForwarding(allow bool) {
s.mu.Lock()
defer s.mu.Unlock()
s.allowRemotePortForwarding = allow
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does allowRemotePortForwarding take effect after we run the Start() function? Is it modifiable at runtime?

Copy link
Collaborator Author

@lixmal lixmal Jul 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's currently static but the field would take effect if changed

@lixmal
Copy link
Collaborator Author

lixmal commented Jul 11, 2025

@pappz

What is the proper way to disable this feature and start using the original sshd configuration?

netbird up --allow-server-ssh=false or through the dashboard

Why do we have multiple lines?

Will fix

Copy link

}

// setupSessionIO connects session streams to local terminal
func (c *Client) setupSessionIO(ctx context.Context, session *ssh.Session) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused ctx

return e.Err
}

var (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Const, vars preferred first, and after the types, functions in the source code

}

// initializeServerState sets up server state after successful setup
func (s *Server) initializeServerState(ln net.Listener, sshServer *ssh.Server) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not see any reason for this function. Maybe it would be better to eliminate.

s.initializeServerState(ln, sshServer)
log.Infof("SSH server started on %s", addrDesc)

go s.serve(ln, sshServer)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you pass ln and sshServer as parameters if the serve function is not static?

}

s.sshServer = nil
s.listener = nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Who closes the s.listener?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it is not required to close, then s.listener variable is unused

return errors.New("invalid local NetBird address")
}

if err := e.firewall.AddInboundDNAT(localAddr, firewallManager.ProtocolTCP, 22, 22022); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these ports not configurable by command line?

@pappz pappz self-requested a review July 21, 2025 13:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants