Cannot SSH into QEMU virtual machine running dropbear sshd - arm

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 root#127.0.0.1
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
root#127.0.0.1'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 root#192.168.160.150
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)?

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.

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

Related

How to prevent the ip address of hyper-v virtual switch from being changed?

I have a laptop with Windows 10 2004 installed. I configureded Hyper-V and created two VMs: On one VM runs windows 10 to enclose serveral malware IM softwares which I have to use for working contacts. On the other VM runs ubuntu server 20.04 for development.
I configured Hyper-V with a virtual switch of type internal network and Hyper-V automatically specified the virtual switch with a static IP. I want to connect to ubuntu with machine name. So I specified ubuntu VM with a static IP and added an item in the hosts file of the host windows 10. Then I can use the remote over SSH feature of VS Code to develop node.js app in windows 10 host. Everything went ok till I had restarted my laptop.
After I have restarted the laptop, the IP address of the hyper-v virtual switch was changed. I couldn't reconnect to VM ubuntu any more because the VM ubuntu was configured with a static IP and default gateway based on the old IP of the virtual switch.
I checked the IPv4 properties of the virtual switch via UI, It's configured as "using the following IP", so I thought of the IP shouldn't change. But I was wrong. Each time after my laptop being restarted, the "static IP" of virtual switch always changes. This change breaks the connection to VM ubuntu.
So, is there any way to prevent the IP address of the virtual switch from being changed? Or some way to add name resolving mechanism to Hyper-V virtual switch (then I can configure using dynamic IP address in VMs)?
I just added an additional Internal switch via Hyper-V "Virtual Switch Manager" and gave it a name of "Static Switch". Then changed it's settings via Control Panel->Network and Internet->Network and Sharing Center->Change adapter settings. Right click on the new adapter and select Properties->Internet Protocol Version 4 (TCP/IPv4) and set a static IP that is not currently used on your network, for example IP address: 192.168.199.1 Subnet mask: 255.255.255.0. No other settings are required. Click Ok and close all the parent windows.
Add the new nic to the Hyper-V machine via the settings for the VM, Add Hardware->Network Adapter-Add. Select the 'Static Switch' and click OK.
Edit your client virtual machine network settings, in my case Ubuntu 20.10 so it's Wired Settings for eth1 (the new 'Wired Connection'). I disabled IPv6 and edited the IPv4 settings using a manual configuration (static IP) setting the IP address to 192.168.199.2 and a net mask of 255.255.255.0 and a gateway of 192.168.199.1 (The 'Static Switch'). No other settings are required. Click Apply and check that the network eth1 is connected.
You should be able to ping 192.168.199.1 from the client VM and ping 192.168.199.2 from the host machine.
This configuration will persist after a reboot and you can edit your hosts file on the host machine with whatever name you want, eg 192.168.199.2 my.vm.machine
Note: You will need to edit the hosts file as an administrator.
Don't use the default switch created by Hyper-V. As Miket25 said: "The default switch is made by HNS, and there may be settings that causes it to have a DHCP address on reboot".
Create a internal virtual switch using NAT annually. Here is the guide. And then connect VMs to this switch. The static IP address assigned to this switch will not be changed through rebooting.
Setting Static IP address in Ubuntu in Hyperv
Note: VM(s) are connected on "External Switch" in Hyperv
Check DNS IP address VM uses
gtan#master:~$ systemd-resolve --status
...
Link 2 (eth0)
Current Scopes: DNS
LLMNR setting: yes
MulticastDNS setting: no
DNSSEC setting: no
DNSSEC supported: no
DNS Servers: 192.168.141.81
DNS Domain: mshome.net
Check Gateway and Subnet Mask
gtan#master:/etc/netplan$ netstat -r
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
default _gateway 0.0.0.0 UG 0 0 0 eth0
10.44.0.0 0.0.0.0 255.255.255.0 U 0 0 0 cni0
10.44.1.0 10.44.1.0 255.255.255.0 UG 0 0 0 flannel.1
10.44.2.0 10.44.2.0 255.255.255.0 UG 0 0 0 flannel.1
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 br-894a4759cb12
172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.141.80 0.0.0.0 255.255.255.240 U 0 0 0 eth0
_gateway 0.0.0.0 255.255.255.255 UH 0 0 0 eth0
eth0 Gateway = 192.168.141.81 mask 255.255.255.240 (192.168.141.80 is for broadcast)
Check eth0 IP address and subnet mask
gtan#master: ifconfig
...
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.141.85 netmask 255.255.255.240 broadcast 192.168.141.95
inet6 fe80::215:5dff:fe3a:1100 prefixlen 64 scopeid 0x20<link>
ether 00:15:5d:3a:11:00 txqueuelen 1000 (Ethernet)
RX packets 82792 bytes 103449317 (103.4 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 40353 bytes 10745111 (10.7 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
...
Edit "/etc/netplan/01-netcfg.yaml" to this (make a backup of the orginal 01-netcfg.yaml first: "sudo cp ./01-netcfg.yaml ./01-netcfg.yaml.bak"):
network:
version: 2
renderer: networkd
ethernets:
eth0:
dhcp4: no
addresses:
- 192.168.141.85/28
gateway4: 192.168.141.81
nameservers:
addresses: [8.8.8.8]
Shutdown the VM
In Hyperv, select the VM(s):
Go to Network Adaptor --> Advanced Features --> Set MAC address to "static"
All good to go!!!
After work, use "saved" instead of "paused" for the VMs'

Replace a printer with a pc using serial port

I have to update my question (May 4th). The male db25 connector misled me to the parallel port so I rephrased it.
I have an old computer system that sends live data (temperature from some external devices) to a parallel dot printer. This computer must not be changed.
Instead of printing I would like to connect the printer cable in an (ubuntu os) pc serial port in order to receive those data and redirecting them in stdout.
Checking the db25 pins I discovered that it is used as RS232 serial cable. There are only three pin connected:
pin 2 (TXD)
pin 3 (RXD)
pin 7 (GND)
So my intentions are firstly to connect those pins to a db9 serial connector in order to plug it in a pc serial port and secondly to open and read the input data using:
chmod o+rw /dev/ttyS0
cat -v < /dev/ttyS0
I believe that it is a simple solution and it is going to work.

How to send a packet to the kernel?

I have two interfaces in my Linux system - eth0 and eth1. I have opened a raw socket on eth0 and I am listening on it for incoming packets. When a packet comes from eth0, I forward it to eth1 after changing the ethernet header (specifically destination MAC to eth1's MAC address). The packet should now be accepted by the interface and sent to the kernel for further processing and eventually to the application waiting for it. But for some reason the packet reaches eth1 (as I can see from wireshark) but the application does not receive it (the application is ping and I don't see the ping reply).
How do I send the packet to eth1 such that it is accepted and sent upstream to the kernel?
There is probably a misunderstanding here:
If you send a packet through a raw socket on an interface, in your case eth1, it will not be treated as local to the kernel, regardless of its mac-address, but will leave the interface to the network (with its own mac-address as destination). This is what you observe with wireshark.
If you want the packet to be processed by your kernel, send it to the lo-interface (Loopback-interface), which is specifically for that purpose.

Can u-boot support more than one ethernet port?

I want to ping out of multiple ethernet ports. Is there an inherent restriction where u-boot only supports a single ethernet port?
Can u-boot support more than one ethernet port?
Yes, in recent versions of U-Boot (going back to at least 2012.10).
Salient code is eth_current_changed() and eth_set_current() in net/eth.c.
Is there an inherent restriction where u-boot only supports a single ethernet port?
No, recent versions of U-Boot can support more than one Ethernet port on the board.
When more than one Ethernet interface is available (as reported by the "Net" device list on startup, e.g. "Net: macb0, gmac0, usb_ether"), the environment variable ethact is used to define the selected Ethernet interface that is active.
Use the printenv ethact command to view the current selection.
Use the setenv ethact <port name> to change the active Ethernet port.
The U-Boot network commands, such as ping and tftpboot, will use the Ethernet port defined by the ethact variable. This preserves the command syntax with older versions of U-Boot, and the syntax is consistent regardless of the number of available ports (e.g. scripts do not change).
Each Ethernet port is assigned its own MAC address, using the following environment variables:
ethaddr: Ethernet MAC address for first/only ethernet interface (= eth0 in Linux).
This variable can be set only once (usually during manufacturing of the board). U-Boot refuses to delete or overwrite this variable once it has been set.
eth1addr: Ethernet MAC address for second ethernet interface (= eth1 in Linux).
eth2addr: Ethernet MAC address for third ethernet interface (= eth2 in Linux).
Obviously you can only (easily) access one port at a time.
There is also only one static IP address assignment, i.e. the ipaddr environment variable.
(I don't know what happens with an IP address acquired by DHCP using one port, and then the active port is changed.)
U-Boot> printenv ethact
ethact=macb0
U-Boot> setenv ethact gmac0
U-Boot> ping 192.168.1.1
gmac0: PHY present at 7
gmac0: Starting autonegotiation...
gmac0: Autonegotiation complete
gmac0: link up, 1000Mbps full-duplex (lpa: 0x2800)
Using gmac0 device
host 192.168.1.1 is alive
U-Boot>
Note that there also a rotation scheme that automatically changes the active port when the ports are down:
U-Boot> printenv ethact
ethact=gmac0
U-Boot> ping 192.168.1.1
gmac0: PHY present at 7
gmac0: Starting autonegotiation...
gmac0: Autonegotiation timed out (status=0x7949)
gmac0: link down (status: 0x7949)
ERROR: Need valid 'usbnet_devaddr' to be set
at drivers/usb/gadget/ether.c:2362/usb_eth_init()
macb0: PHY present at 0
macb0:0 is connected to macb0. Reconnecting to macb0
macb0: Starting autonegotiation...
macb0: Autonegotiation timed out (status=0x7849)
macb0: link up, 100Mbps full-duplex (lpa: 0x41e1)
Using macb0 device
ping failed; host 192.168.1.1 is not alive
U-Boot> printenv ethact
ethact=macb0
U-Boot>

Adding multiple ipv6 addresses to a single interface using ioctl

I am trying to port my application to ipv6 and my current code brings up alias IP addresses dynamically as shown:
eth0 Link encap:Ethernet HWaddr 00:16:35:68:21:5B
inet addr:192.168.1.245 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::216:35ff:fe68:215b/64 Scope:Link
UP BROADCAST RUNNING MTU:1500 Metric:1
RX packets:278885750 errors:0 dropped:0 overruns:0 frame:0
TX packets:68117973 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:68976932662 (64.2 GiB) TX bytes:39384521280 (36.6 GiB)
Interrupt:169
eth0:1 Link encap:Ethernet HWaddr 00:16:35:68:21:5B
inet addr:192.168.1.246 Bcast:192.168.1.255 Mask:255.255.255.0
UP BROADCAST RUNNING MTU:1500 Metric:1
Interrupt:169
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:6060179 errors:0 dropped:0 overruns:0 frame:0
TX packets:6060179 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2366257047 (2.2 GiB) TX bytes:2366257047 (2.2 GiB)
eth0:1 will be added dynamically by the application. It uses ioctl to do this. I want to do the same for IPV6 address. I tried this Assign ipv6 address using ioctl. But the example code is adding IPV6 address to the existing interface eth0 instead of eth0:1 or eth0:2 even if I specify the interface name as eth0:1. Can anyone please help since I am new to IPV6.
This is normal behaviour. In IPv4 each interface could have only one address. To add more addresses you had to create 'fake' interfaces like eth0:1. IPv6 always has multiple addresses per interface so work-arounds like eth0:1 are not used for IPv6.

Resources