Connecting an ssh bridge between two localhosts

Greetings!

I’ve got a brand new Dell laptop with NixOS successfully i nstalled. I’m using the Gnome spin and have a few basic apps installed. It’s connected to the internet and I can browse the web with Firefox.

The next task I am working on is establishing an ssh connection over WiFi between my other local Linux PC (running Manjaro).

On both hosts I have confirmed that the Open SSH Daemon is active.

On my NixOS laptop inside my /etc/nixos/configuration.nix I have uncommented the lines which say:

services openssh enable = true;

…as well as:

networking.firewall enable = false;

(I realize that disabling the firewall is not a good security practice. I am only doing this temporarily to successfully establish the ssh connection for the first time and then afterwards I will obviously re-enable the firewalls and explore more secure firewall configuration options.)

The status of my firewall on my other Linux host is (temporarily) disabled as well.

$ ssh <remote-username>@fe80::ebaa:74b5:6ad:918
ssh: connect to host fe80::ebaa:74b5:6ad:918 port 22: Invalid argument

Even if I wrap the ip address in square brackets, that doesn’t help.

I can’t even ping the NixOS host from my Manjaro host:

$ ping fe80::ebaa:74b5:6ad:918%wlp2s0     
ping: fe80::ebaa:74b5:6ad:918%wlp2s0: Name or service not known

$ ping6 fe80::ebaa:74b5:6ad:918%wlp2s0 
ping6: fe80::ebaa:74b5:6ad:918%wlp2s0: Name or service not known

What might you folks suggest I try next?

I found the official NixOS Wiki doc on OpenSSH configuration: SSH - NixOS Wiki
This doc will help after I successfully connect. For now it is not immediately relevant since I have enabled openssh as well as disabled the firewall in just those two lines as quoted above in my configuration.nix (temporarily).

What other information could I provide to help troubleshoot?

configuration.nix
# Edit this configuration file to define what should be installed on
# your system.  Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running ‘nixos-help’).

{ config, pkgs, lib, ... }:

{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];

  nixpkgs.config.allowUnfree = true;

  # Bootloader
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  networking.hostName = "nixos-laptop"; # Define your hostname.
  # networking.wireless.enable = true;  # Enables wireless support via wpa_supplicant.

  # Configure network proxy if necessary
  # networking.proxy.default = "http://user:password@proxy:port/";
  # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";

  # Enable networking
  networking.networkmanager.enable = true;

  # Set your time zone.
  time.timeZone = "America/New_York";

  # Select internationalisation properties.
  i18n.defaultLocale = "en_US.UTF-8";

  i18n.extraLocaleSettings = {
    LC_ADDRESS = "en_US.UTF-8";
    LC_IDENTIFICATION = "en_US.UTF-8";
    LC_MEASUREMENT = "en_US.UTF-8";
    LC_MONETARY = "en_US.UTF-8";
    LC_NAME = "en_US.UTF-8";
    LC_NUMERIC = "en_US.UTF-8";
    LC_PAPER = "en_US.UTF-8";
    LC_TELEPHONE = "en_US.UTF-8";
    LC_TIME = "en_US.UTF-8";
  };

  # Enable the X11 windowing system.
  services.xserver.enable = true;

  # Enable the GNOME Desktop Environment.
  services.xserver.displayManager.gdm.enable = true;
  services.xserver.desktopManager.gnome.enable = true;

  # Configure keymap in X11
  services.xserver.xkb = {
    layout = "us";
    variant = "";
  };

  # Enable CUPS to print documents.
  services.printing.enable = true;

  # Enable sound with pipewire.
  hardware.pulseaudio.enable = false;
  security.rtkit.enable = true;
  services.pipewire = {
    enable = true;
    alsa.enable = true;
    alsa.support32Bit = true;
    pulse.enable = true;
    # If you want to use JACK applications, uncomment this
    #jack.enable = true;

    # use the example session manager (no others are packaged yet so this is enabled by default,
    # no need to redefine it in your config for now)
    #media-session.enable = true;
  };

  # Enable touchpad support (enabled default in most desktopManager).
  # services.xserver.libinput.enable = true;

  # Define a user account. Don't forget to set a password with ‘passwd’.
  users.users.<username> = {
    isNormalUser = true;
    description = "<petname>";
    extraGroups = [ "networkmanager" "wheel" ];
    packages = with pkgs; [
    #  thunderbird
    ];
  };

  # Install firefox.
  programs.firefox.enable = true;

  # List packages installed in system profile. To search, run:
  # $ nix search wget
  environment.systemPackages = with pkgs; [
  vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
  wget
  google-chrome
  gotop
  foot
  radeontop
  git
  nerdfonts
  gnome-terminal
  # locate
  python3
  curl
  vscode
  fastfetch
  signal-desktop
  openssh
  gedit
];

  # Some programs need SUID wrappers, can be configured further or are
  # started in user sessions.
  # programs.mtr.enable = true;
  # programs.gnupg.agent = {
  #   enable = true;
  #   enableSSHSupport = true;
  # };

  # List services that you want to enable:

  # Enable the OpenSSH daemon.
  services.openssh.enable = true;

  # Open ports in the firewall.
  # networking.firewall.allowedTCPPorts = [ ... ];
  # networking.firewall.allowedUDPPorts = [ ... ];
  # Or disable the firewall altogether.
  networking.firewall.enable = false;

  # This value determines the NixOS release from which the default
  # settings for stateful data, like file locations and database versions
  # on your system were taken. It‘s perfectly fine and recommended to leave
  # this value at the release version of the first install of this system.
  # Before changing this value read the documentation for this option
  # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
  system.stateVersion = "24.11"; # Did you read the comment?

}
sshd status
$ systemctl status sshd
● sshd.service - SSH Daemon
     Loaded: loaded (/etc/systemd/system/sshd.service; enabled; preset: ignored)
     Active: active (running) since Mon 2024-12-09 03:09:38 EST; 1h 39min ago
 Invocation: 4f5c29fa060041878d174fab4ae45254
   Main PID: 8801 (sshd)
         IP: 0B in, 0B out
         IO: 788K read, 16K written
      Tasks: 1 (limit: 18386)
     Memory: 1.9M (peak: 3.1M)
        CPU: 509ms
     CGroup: /system.slice/sshd.service
             └─8801 "sshd: /nix/store/nfjjkzr25i7qj2r0vslb242jbadb1k4j-openssh-9.9p1/bin/sshd -D -f />

When you use IPv6 link-local addresses, you always need to provide the interface with % as a delimiter at the end like you did with the ping calls below.

While the notation of the IPv6 address with the interface looks syntactically correct here, please verify that wlp2s0 is in fact the name of the wireless interface on your device. The error message typically indicates that the interface name is unknown.

1 Like

It might help if I could show the output of: $ ip addr show. That would reveal all the ways my laptop can be accessed. Is that correct? Would that help you folks guide me to choose the right ssh destintation address?

If I were to share that output here on this public forum, would that make me vulnerable to attack? Would that be bad security practices? Is there a way for me to share my local IPv6 addresses while remaining protected?

It’s as @fpletz explained. You just need to add the host’s interface name to the IPV6 address. Consider the following example:

Host:

  • interface: wlp3s0
  • inet6: 2b63:bec4:08e2:4b7f:1317:4723:41e7:20fa

Remote:

  • interface: wlp2s0
  • inet6: 913a:96e8:4a91:36ad:b327:c1b5:19cc:a86a

In this case, you can connect with:

$ ssh "<remote-username>@913a:96e8:4a91:36ad:b327:c1b5:19cc:a86a%wlp3s0"

Remote username = evangelist

From the shell of my Host:


$ ssh "evangelist@913a:96e8:4a91:36ad:b327:c1b5:19cc:a86a%wlp3s0" 
ssh: Could not resolve hostname 913a:96e8:4a91:36ad:b327:c1b5:19cc:a86a%wlp3s0: Name or service not known

$ ssh evangelist@913a:96e8:4a91:36ad:b327:c1b5:19cc:a86a%wlp3s0   
ssh: Could not resolve hostname 913a:96e8:4a91:36ad:b327:c1b5:19cc:a86a%wlp3s0: Name or service not known

$ ssh [evangelist]@[913a:96e8:4a91:36ad:b327:c1b5:19cc:a86a%wlp3s0] 
zsh: no matches found: [evangelist]@[913a:96e8:4a91:36ad:b327:c1b5:19cc:a86a%wlp3s0]

Does pinging work?

$ ping -6 "913a:96e8:4a91:36ad:b327:c1b5:19cc:a86a%wlp3s0"

If not, you should probably double-check that everything is named correctly.

I’m curious, though, is this a local network? and if so, why not just use IPV4? or is there a certain advantage to using IPV6 here?

It is a local network. The main host (Manjaro) is connected directly into the modem via ethernet. The laptop “remotehost” (NixOS) connection is over WiFi. These were the addresses leased either by the DHCP server or what ever other tool NixOS (or perhaps the modem) assigned. I did not specifically request IPv6. It’s what I discovered upon running $ ip add show on both machines.

Pinging does not work:

$ ping -6 "913a:96e8:4a91:36ad:b327:c1b5:19cc:a86a%wlp3s0"
ping: 913a:96e8:4a91:36ad:b327:c1b5:19cc:a86a%wlp3s0: Name or service not known

Perhaps I have a typo in my IPv6 address. To confirm this one step further: Is it safe to share the output of: $ ip addr show . If I were to share that output here on this public forum, would that make me vulnerable to attack? Would that be irresponsible security practices?

In this case, the interface name should be something like eno0, eth0, … for ethernet.

So you only see IPV6 addresses on both machines and no IPV4? Does running nmcli give the same result?

I’m no security expert, but I think it’s fine since it’s a local network, but we can continue working with the fictitious example for now, if you’d like. I also doubt having the real addresses will help us much if you’re sure you’re copying them correctly.

The only thing I can think of here is that you shouldn’t include the /64 at the end when copying the address.

I wasn’t able to right click copy and paste the exact addresses because the two hosts don’t share a clip board. Instead I was being as meticulous and careful as I could visuallly looking at the address and then transcribing them with my keyboard, one character at a time.

Before I share the output, it appears the ip addresses and even the device names are all different from when I wrote my first post in this thread 12 hours ago. I am certain that my remotehost network device name was previously wlp3s0 and now it is showing wlp2s0. The 3 now shows 2. All the IP addresses are completely different now as well. Anyways, without further adieu, here is the current output from my remotehost:

$ ip add show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute 
       valid_lft forever preferred_lft forever
2: wlp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 44:fa:66:c4:a6:55 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.5/24 brd 10.0.0.255 scope global dynamic noprefixroute wlp2s0
       valid_lft 169132sec preferred_lft 169132sec
    inet6 2607:fea8:555c:1e00::d4ee/128 scope global dynamic noprefixroute 
       valid_lft 601133sec preferred_lft 169133sec
    inet6 2607:fea8:555c:1e00:b00:a703:4b8c:fd42/64 scope global temporary dynamic 
       valid_lft 295sec preferred_lft 295sec
    inet6 2607:fea8:555c:1e00:dad4:2e20:5898:2664/64 scope global dynamic mngtmpaddr noprefixroute 
       valid_lft 295sec preferred_lft 295sec
    inet6 fe80::ebaa:74b5:6ad:918/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
$ nmcli
wlp2s0: connected to <SSID>
        "Realtek RTL8821CE"
        wifi (rtw_8821ce), 44:FA:66:C4:A6:55, hw, mtu 1500
        ip4 default, ip6 default
        inet4 10.0.0.5/24
        route4 10.0.0.0/24 metric 600
        route4 default via 10.0.0.1 metric 600
        inet6 2607:fea8:555c:1e00:b00:a703:4b8c:fd42/64
        inet6 2607:fea8:555c:1e00::d4ee/128
        inet6 2607:fea8:555c:1e00:dad4:2e20:5898:2664/64
        inet6 fe80::ebaa:74b5:6ad:918/64
        route6 fe80::/64 metric 1024
        route6 2607:fea8:555c:1e00::/64 metric 600
        route6 default via fe80::1233:bfff:feaa:166c metric 600
        route6 2607:fea8:555c:1e00::d4ee/128 metric 600

lo: connected (externally) to lo
        "lo"
        loopback (unknown), 00:00:00:00:00:00, sw, mtu 65536
        inet4 127.0.0.1/8
        inet6 ::1/128

DNS configuration:
        servers: 64.71.255.204 64.71.255.198
        domains: phub.net.cable.<DN>.com
        interface: wlp2s0

        servers: 2607:f798:18:10:0:640:7125:5204 2607:f798:18:10:0:640:7125:5198
        interface: wlp2s0

Use "nmcli device show" to get complete information about known devices and
"nmcli connection show" to get an overview on active connection profiles.

Consult nmcli(1) and nmcli-examples(7) manual pages for complete usage details.

Making progress with ping:

$ ping -3 fe80::ebaa:74b5:6ad:918 
ping: Warning: IPv6 link-local address on ICMP datagram socket may require ifname or scope-id => use: address%<ifname|scope-id>
PING fe80::ebaa:74b5:6ad:918 (fe80::ebaa:74b5:6ad:918) 56 data bytes
^C
--- fe80::ebaa:74b5:6ad:918 ping statistics ---
39 packets transmitted, 0 received, 100% packet loss, time 38513ms

But ssh still won’t connect to that address:

$ ssh evangelist@fe80::ebaa:74b5:6ad:918%wlp2s0
ssh: Could not resolve hostname fe80::ebaa:74b5:6ad:918%wlp2s0: Name or service not known

$ ssh "evangelist@fe80::ebaa:74b5:6ad:918%wlp2s0"
ssh: Could not resolve hostname fe80::ebaa:74b5:6ad:918%wlp2s0: Name or service not known

If your host machine (Manjaro) is connected using ethernet, then this shouldn’t be wlp2s0. What’s it called on your host?

Manjaro host (ethernet connection):

$ ip add show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute 
       valid_lft forever preferred_lft forever
2: enp7s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 50:eb:f6:5c:e0:0f brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.234/24 brd 10.0.0.255 scope global dynamic noprefixroute enp7s0
       valid_lft 123397sec preferred_lft 123397sec
    inet6 2607:fea8:555c:1e00::7106/128 scope global dynamic noprefixroute 
       valid_lft 547554sec preferred_lft 115554sec
    inet6 2607:fea8:555c:1e00:1314:766a:5991:e148/64 scope global dynamic noprefixroute 
       valid_lft 300sec preferred_lft 300sec
    inet6 fe80::4e65:5098:79ff:6e10/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

The command should be this, then:

ssh "evangelist@fe80::ebaa:74b5:6ad:918%enp7s0"

Does it work?

1 Like

A more secure option would be services.openssh.openFirewall, but that’s already true by default, so you don’t need to do anything to open that port. Even more security would involve, for example, allowlisting machines that are allowed to connect.

2 Likes

Eureka! Yes, this works. I am connected now. Thank you!

Since this morning I closed and reopened the lid to my laptop a few times. I believe this triggered my WiFi connection causing it to disconnect and reconnect. Could this be why all the ip addresses are different now compared to earlier? Is this what is called dynamic IP assignment?

Is there a way to automate this and make it easier such as using a local DNS or perhaps assigning a static IP I know I can always reuse, over and over again?

Also: What do you make of the use of all these IPv6 addersses? I agree that handling IPv4 addresses would be easier.

1 Like

Both, perhaps? You can give the remotehost a static address in your router and then route its address to a hostname. For the latter, the easiest thing you can use is probably the networking.hosts option.

There seems to be only one IPV6 address with an endless validity, the rest are just temporary. From what I’ve read, it’s for improving privacy (also see this for more details).

1 Like

This is a bit more complicated than it needed to be.

One of your machines is 10.0.0.5, the other is 10.0.0.234.

These should be a bit more stable than the v6 addresses - and a bit easier to type.

Most likely the dns server on the device you refer to as the modem is already doing dynamic updates from dhcp, and using the hostnames of the machines is likely already working without any extra configuration.

most likely you can do something like

ssh nixos-laptop

Though you may have some issues with the dash.

You can try seeing what

host 10.0.0.5
host 10.0.0.234

says on each machine.

2 Likes