Cannot SSH into QEMU virtual machine running dropbear sshd

3.6k Views Asked by At

I have set up a QEMU virtual machine emulating the vexpress-a9 machine. I've used buildroot to create the initrd system and I've used the codesourcery cross-compiler that buildroot downloads as part of it's setup to compile the Linux Kernel. This is how I invoke qemu

qemu-system-arm -m 512 -M vexpress-a9 -dtb linux-4.4.192/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -kernel linux-4.4.192/arch/arm/boot/zImage -initrd buildroot/output/images/rootfs.cpio -append "console=ttyAMA0,ip=dhcp" -net nic,model=lan9118 -net user,hostfwd=tcp::2222-:22 -nographic

It boots just fine. Network related boot messages that tell that the network has been initialized and dropbear sshd was brought up and running:

Starting network: OK Starting dropbear sshd: random: dropbear: uninitialized urandom read (32 bytes read, 1 bits of entropy available) OK

however the eth0 interface has to be assigned an IP manually. I assign it an unused class C address in the same subnet as my Linux host like so:

# ifconfig eth0 192.168.160.150 up smsc911x 4e000000.ethernet eth0: SMSC911x/921x identified at 0xa12a0000, IRQ: 31

So ifconfig now shows:

# ifconfig
eth0      Link encap:Ethernet  HWaddr 52:54:00:12:34:56
          inet addr:192.168.160.150  Bcast:192.168.160.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interrupt:31

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

netstat tells me that we are listening on port 22:

# netstat -tln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN

I can even ssh into localhost like so:

# ssh [email protected]
random: ssh: uninitialized urandom read (32 bytes read, 24 bits of entropy available)
random: dropbear: uninitialized urandom read (32 bytes read, 24 bits of entropy available)
random: dropbear: uninitialized urandom read (32 bytes read, 24 bits of entropy available)
random: dropbear: uninitialized urandom read (32 bytes read, 24 bits of entropy available)

Host '127.0.0.1' is not in the trusted hosts file.
(ecdsa-sha2-nistp256 fingerprint sha1!! de:cf:f8:b3:ac:4d:96:47:22:d7:76:a1:ea:11:3d:bc:ec:c6:71:9a)
Do you want to continue connecting? (y/n) y
[email protected]'s password:
random: dropbear: uninitialized urandom read (32 bytes read, 26 bits of entropy available)

whereas from the host this is what I see when I try to SSH into this VM from the linux host:

$ ssh -vvv [email protected]
OpenSSH_7.4p1 Debian-10+deb9u7, OpenSSL 1.0.2s  28 May 2019
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug2: resolving "192.168.160.150" port 22
debug2: ssh_connect_direct: needpriv 0
debug1: Connecting to 192.168.160.150 [192.168.160.150] port 22.
debug1: connect to address 192.168.160.150 port 22: No route to host
ssh: connect to host 192.168.160.150 port 22: No route to host

I would be pleased to have some pointers about this as I cannot find what else can be tried

UPDATE 1: Included dhcpd while configuring buildroot. Now irrespective of whether I use dropbear or openssh, the log messages appear until

Starting dhcpcd...
no interfaces have a carrier <--- the problem
forked to background, child pid 746
smsc911x 4e000000.ethernet eth0: SMSC911x/921x identified at 0xa12a0000, IRQ: 31
Starting dropbear sshd: random: dropbear: uninitialized urandom read (32 bytes read, 2 bits of entropy available)
OK
random: dhcpcd: uninitialized urandom read (120 bytes read, 2 bits of entropy available)

at which point it just kind of stops and I cannot see the login prompt. Upon removing dhcpd and using either dropbear or openssh, I can see the login prompt again (meaning all the init scripts run to completion) but again no connectivity of any kind. I can't understand why in the world does dhcpd thinks we have no carrier (when it is able to enumerate and identify the emulated NIC card)

UPDATE2: I've tried invoking udhcpc manually to obtain an address via DHCP and it does get an address

# udhcpc -S -a100
udhcpc: started, v1.31.0
udhcpc: sending discover
udhcpc: sending select for 10.0.2.15
udhcpc: lease of 10.0.2.15 obtained, lease time 86400
deleting routers
adding dns 10.0.2.3
# ifconfig
eth0      Link encap:Ethernet  HWaddr 52:54:00:12:34:56
          inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:4 errors:0 dropped:0 overruns:0 frame:0
          TX packets:5 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:2360 (2.3 KiB)  TX bytes:1428 (1.3 KiB)
          Interrupt:31

The machine is still however inaccessible from the host. Do I need to add a manual route to this VM from the host? If yes how do I do that? Does QEMU create a virtual interface on the host (like workstation does)?

2

There are 2 best solutions below

0
On

I spent hours yesterday trying different options (i.e. -net, -netdev) with qemu-system-arm, but finally what worked was this one option: -nic user,hostfwd=::2222-:22 Which I learned from the list of removed features page (look at replacement of -redir option). I also had to add these 3 lines in my host's SSH config file: /etc/ssh/ssh_config

Host localhost
PreferredAuthentications=password
PubkeyAuthentication=no
6
On

If you're using QEMU's 'user' mode networking, then trying to assign the guest an IP address in your host's network is wrong. User mode network creates a little emulated network with its own DHCP server -- you can see a diagram of this at https://wiki.qemu.org/Documentation/Networking#User_Networking_.28SLIRP.29

By default the network the guest sits on is 10.0.2.x, but you can change it with command line arguments.

The simplest way to configure the guest is to have it run a DHCP client, which should be able to find the built-in DHCP server QEMU provides it and get an IP address on the emulated-network that way.

An important point about user mode networking is that it does not allow you to generally connect directly to the guest VM from the host. The only way to connect to it is if your QEMU command line specifies particular ports to forward from the host to the guest -- if you do that then you can connect to the host IP address and port that you specified in the command line forwarding option and it will be forwarded to the guest's IP address and port on the emulated network.

If this is not sufficient and you need the VM to appear on a real virtual interface that is bridged to the host's networking, then you should stop using user mode networking and look at the TAP networking option instead. TAP is however more complicated to set up.