Friday, 27 November 2020

Connecting with my parents

I have installed a Raspberry Pi Zero at my parents' house in the summer to connect our LAN networks better. One particular use case is streaming at my parents' house via my broadband access. For this reason, I have dynamic DNS and PiVPN with WireGuard on the Raspberry Pi 1 at our house. This enables the use case for hosts that can install a WireGuard client. For hosts that can not install WireGuard client like Chromecast, the need emerges to build a small island at my parents' house with complete DHCP/WiFi infrastructure connected to the Internet via my broadband access. I used a small USB WiFi stick plugged into the USB hub with Ethernet that is connected to the Raspberry Pi Zero at my parents' house. Using this USB WiFi stick as an access point with hostapd and running dnsmasq for DHCP, I could build the basic infrastructure.

pi@pi0:~ $ sudo apt install hostapd
pi@pi0:~ $ sudo systemctl unmask hostapd
pi@pi0:~ $ sudo systemctl enable hostapd
pi@pi0:~ $ sudo nano /etc/hostapd/hostapd.conf
country_code=HU
interface=wlan0
ssid=ralink
hw_mode=g
channel=1
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=*****************
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
pi@pi0:~ $ sudo rfkill unblock wlan
pi@pi0:~ $ sudo nano /etc/dhcpcd.conf
interface wlan0
static ip_address=192.168.3.1/24
nohook wpa_supplicant
pi@pi0:~ $ sudo apt install dnsmasq
pi@pi0:~ $ sudo nano /etc/dnsmasq.conf
interface=wlan0
dhcp-range=192.168.3.2,192.168.3.20,255.255.255.0,24h
dhcp-option=6,8.8.8.8

As PiVPN on both sides were using conflicting IP addresses and WireGuard client can only be installed on Raspberry Pi OS based on Debian Buster with the hassle of backporting it from Debian Bullseye, I installed ZeroTier. For some reason, ZeroTier 1.6.1 does not install flawlessly on Raspberry Pi Zero so I had to make them from the git repository.

UPDATE

ZeroTier 1.6.2-2 now installs flawlessly on both Raspberry Pi Zero.

UPDATE 2

It turned out that Raspberry Pi 1 700 MHz CPU could not cope hairpin streaming with ZeroTier. Please note that hairpin streaming with WireGuard might be a working option even on Raspberry Pi 1 but it seems to be a hassle to backport WireGuard client from Debian Bullseye. Fortunately, I had an unused Raspberry Pi Zero W lying around as the only aerial position that provides good enough signal to its DVB-T hat is from my daughters' window upstairs and she refused to keep the window slightly open all day long for permanent installation. So instead of trying to move the setup over to WireGuard on Raspberry Pi 1 that has a lot of other duties anyway in my home, I gave this Raspberry Pi Zero W a try. It turned out that 1 GHz CPU clock speed is just enough for hairpin streaming with zerotier.

The resulting and relevant IP configuration with ASCII diagram is as follows:

pi@pi0w:~ $ ip a
wlan0: inet 192.168.1.10/24
zt5u4vfg76: inet 192.168.193.236/24

pi@pi0:~ $ ip a
eth0: inet 192.168.8.151/24
zt5u4vfg76: inet 192.168.193.79/24
wlan0: 192.168.3.1/24

wlan0 zt5u4vfg76 zt5u4vfg76 eth0
  |  ----------------------  |
  | |                      | |
 ------                   -----
| pi0w |                 | pi0 |
 ------                   -----
                           |
                           |/|
                             |
                          wlan0

The trickiest part of the routing is to direct the traffic from the small island DHCP/WiFi infrastructure into the ZeroTier link instead of the default route. I use a source-based rule with a separate routing table for this as follows, starting with enabling routing on both sides:

pi@pi0w:~ $ sudo nano /etc/sysctl.d/routed-ap.conf
net.ipv4.ip_forward=1

pi@pi0:~ $ sudo nano /etc/sysctl.d/routed-ap.conf
net.ipv4.ip_forward=1

pi@pi0:~ $ sudo nano /lib/dhcpcd/dhcpcd-hooks/40-route
/sbin/ip rule add from 192.168.3.0/24 table 1
/sbin/ip route add 192.168.3.0/24 via 192.168.3.1 table 1 
/sbin/ip route add default via 192.168.193.236 table 1

On my side of the ZeroTier link, I used NAT as follows:

pi@pi0w:~ $ sudo iptables -t nat -I POSTROUTING -j MASQUERADE
pi@pi0w:~ $ sudo iptables-save -f /etc/iptables.rules
pi@pi0w:~ $ sudo nano /etc/rc.local
iptables-restore /etc/iptables.rules

For static route for reverse traffic I used advanced manage route function on zero tier as follows:




To make this configuration persistent, I saved iptables rules and added ip commands to dhcpcd hooks.
The connection can be tested with tcpdump as follows:

pi@pi0w:~ $ sudo tcpdump -i zt5u4vfg76 net 192.168.3.0/24

UPDATE after 4 years

jordana@pi4g:~ $ sudo nano /etc/rc.local
#!/bin/bash
iptables-restore /etc/iptables.rules
jordana@pi4g:~ $ sudo chmod +x /etc/rc.local
jordana@pi4g:~ $ sudo reboot
jordana@pi4g:~ $ journalctl -b | grep rc.local
Dec 23 09:23:29 pi4g systemd[1]: Starting rc-local.service - /etc/rc.local Compatibility...
Dec 23 09:23:29 pi4g systemd[1]: Started rc-local.service - /etc/rc.local Compatibility.

Saturday, 31 October 2020

Building a Raspberry Pi 4 laptop

I was watching a lot of YouTube videos where people gave Raspberry Pi 4 a try as their primary PC. I got tempted myself but lacking a desk I had to explore the options of building a laptop based on Raspberry Pi 4. I have done a similar test with my Samsung 10-inch tablet in a Bluetooth keyboard case but as it still runs Android Nougat and has 1G of memory only the experience is really slow. The most important match to find was a Bluetooth keyboard case with a monitor. As a pointing device with a computer, the touchpad was a necessity on the keyboard too. In terms of size I was aiming at 10-inch again and found a reasonable match on Amazon:

10-inch monitor

Bluetooth keyboard and touchpad case

I managed to tie my Raspberry Pi and a big 20,000 mAh power bank to the case and used short USB power and HDMI cables to connect it all. 


The overall experience is pretty reasonable on Raspberry Pi OS. Unfortunately Bluetooth is not stable on Ubuntu desktop yet. YouTube in Chromium browser is playing without a noticable drop of frames up to 720p but even 1080p60 is watchable. Email and chat are widely supported with the exception of the Outlook desktop experience and WhatsApp Web. Lack of built in microphone makes it more difficult to test voice calls but even with a USB sound card the result is dubious. Telegram desktop does not recognise the USB sound card and Messenger from Chromium does not provide stable voice calls either. With some hacking even Netflix and Amazon Prime are running fine in Chromium. As the monitor has a second HDMI input the other use case that I am trying is Samsung Dex from my Galaxy S10. First try with a USB-C to HDMI adapter was quite reasonable also however not all apps are working fine. Netflix and BBC iPlayer are notable examples of apps that are not functioning correctly. To minimise the cableing I have a Miracast dongle shipping that I plan to test soon.

Saturday, 10 October 2020

[Updated] Removing quiet and splash options from command line of Debian RPD live USB with persistence

The excuse to remove quiet and splash options from the kernel command line of my Debian RPD live USB with persistence was the tty consoles did not reliably setup increased font size with dpkg-reconfigure console-setup on bootup. I have found xorriso and its alter ego osirrox to extract grub.cfg, remove the quiet and splash options and write it over back in the ISO image.

pi@raspberrypi:~ $ osirrox -dev Downloads/2020-02-12-rpd-x86-buster.iso
-extract boot/grub/grub.cfg grub.cfg
xorriso 1.5.0 : RockRidge filesystem manipulator, libburnia project.
xorriso : NOTE : Loading ISO image tree from LBA 0
xorriso : UPDATE : 5398 nodes read in 1 seconds
xorriso : NOTE : Detected El-Torito boot information which currently is set to be discarded
Drive current: -dev 'Downloads/2020-02-12-rpd-x86-buster.iso'
Media current: stdio file, overwriteable
Media status : is written , is appendable
Boot record : El Torito , MBR isohybrid cyl-align-on GPT APM
Media summary: 1 session, 1527416 data blocks, 2983m data, 521m free
Volume id : 'Debian RPD M-A 1'
xorriso : UPDATE : 1 files restored ( 1828b) in 1 seconds = 0.0xD
Extracted from ISO image: file '/boot/grub/grub.cfg'='/home/pi/grub.cfg'
pi@raspberrypi:~ $ chmod +w grub.cfg
pi@raspberrypi:~ $ nano grub.cfg
pi@raspberrypi:~ $ chmod -w grub.cfg
pi@raspberrypi:~ $ xorriso -indev 2020-02-12-rpd-x86-buster.iso /
-outdev 2020-02-12-rpd-x86-buster-mod.iso /
-map '/home/pi/grub.cfg' '/boot/grub/grub.cfg' /
-overwrite nondir /
-boot_image any keep /
-close off /
-write_type auto /
-stream_recording data /
-commit
xorriso : UPDATE : 5398 nodes read in 1 seconds
xorriso : NOTE : Loading ISO image tree from LBA 0
Drive current: -indev '/mnt/2020-02-12-rpd-x86-buster.iso'
xorriso : NOTE : Detected El-Torito boot information which currently
is set to be discarded
Media current: stdio file, overwriteable
Media summary: 1 session, 1527416 data blocks, 2983m data, 754g free
Media status : is written , is appendable
Boot record : El Torito , MBR isohybrid cyl-align-on GPT APM
Volume id : 'Debian RPD M-A 1'
Media summary: 0 sessions, 0 data blocks, 0 data, 754g free
Drive current: -outdev '/mnt/2020-02-12-rpd-x86-buster-mod.iso'
Media current: stdio file, overwriteable
Media status : is blank
xorriso : UPDATE : 1 files added in 1 seconds
xorriso : UPDATE : Writing: 4512s 0.3% fifo 0% buf 50%
Added to ISO image: file '/boot/grub/grub.cfg'='/home/pi/grub.cfg'
xorriso : NOTE : Keeping boot image unchanged
xorriso : UPDATE : Writing: 2048s 0.1% fifo 2% buf 50%
Writing to '/mnt/2020-02-12-rpd-x86-buster-mod.iso' completed successfully.
xorriso : UPDATE : Writing: 16384s 1.1% fifo 81% buf 50% 17.5xD
...
xorriso : UPDATE : Writing: 1523712s 99.9% fifo 75% buf 50% 18.7xD
ISO image produced: 1525788 sectors
Written to medium : 1525952 sectors at LBA 32
xorriso : UPDATE : 5398 nodes read in 1 seconds
xorriso : NOTE : Re-assessing -outdev '/mnt/2020-02-12-rpd-x86-buster-mod.iso'
xorriso : NOTE : Loading ISO image tree from LBA 0
libburn : SORRY : Read start address 1527415s larger than number of readable blocks 1525984
xorriso : NOTE : Detected El-Torito boot information which currently is set to be kept
unchanged
xorriso : NOTE : Tolerated problem event of severity 'SORRY'
Drive current: -dev '/mnt/2020-02-12-rpd-x86-buster-mod.iso'
Media current: stdio file, overwriteable
Media status : is written , is appendable
Boot record : El Torito , MBR cyl-align-on GPT APM
Media summary: 1 session, 1525788 data blocks, 2980m data, 751g free
Volume id : 'Debian RPD M-A 1'
xorriso : NOTE : -return_with SORRY 32 triggered by problem severity SORRY

xorriso : UPDATE : 5398 nodes read in 1 seconds
xorriso : UPDATE : 5398 nodes read in 1 seconds

This made increased font size reliably setup during boot of Debian RPD live USB with persistence.

[Update]

As my cheap USB SATA SSD frequently stopped working with kernel messages that suggested uas
driver is the culprit. So in order to fall back on legacy storage driver, I have looked up the idVendor and
idProduct in dmesg of my cheap USB SATA SSD and added this to the kernel command line:

usb_storage.quirks=2109:0715:u

Wednesday, 7 October 2020

Appearance fine tuning

As my eyes are getting weaker, I do not feel comfortable with the default font size on my 14" laptop screen using 1920x1080 resolution. I had to add this file to make fonts bigger:

pi@raspberrypi:~ $ nano .Xresources 
Xft.dpi: 140

This made the taskbar icons look smaller, so I increased them in Appearance Settings.

For tty, that I very rarely use I have set up the maximal 16x32 characters using:

pi@raspberrypi:~ $ sudo dpkg-reconfigure console-setup

Monday, 5 October 2020

Boosting Raspberry Pi Desktop experience with SSD

While my sleek SanDisk Cruzer Fit was great to give me the initial insight into Debian with Raspberry Pi Desktop, it is so sluggish that seriously deteriorates user experience. As a matter of fact, this SanDisk Cruzer Fit USB 2.0 flash drive is so slow that it even fails Raspberry Pi Diagnostics badly. At the same time, Raspberry Pi OS has recently made booting from USB officially supported on Raspberry Pi 4b.

As both of my laptop and the Raspberry Pi 4b supports USB 3, it made me look into investing a bootable USB 3 solution. In these investment investigations, I usually try to find the cheapest solution on Amazon. I have found for £10 a 64 GB M2 2242 SATA SSD that fits into a £20 USB 3 enclosure. While it sticks out of my laptop much more than the SanDisk Cruzer Fit did, the responsiveness it offers made me stick with it.

Just for the records, I have run Raspberry Pi Diagnostics on this new SSD drive both in my laptop and in the Raspberry Pi 4b.

Here are the results in my laptop:

Raspberry Pi Diagnostics - version 0.5
Sun Oct  4 18:13:59 2020
Test : SD Card Speed Test
Run 1
prepare-file;0;0;156410;305
seq-write;0;0;163024;318
rand-4k-write;0;0;16137;4034
rand-4k-read;16773;4193;0;0
Sequential write speed 163024 KB/sec (target 10000) - PASS
Random write speed 4034 IOPS (target 500) - PASS
Random read speed 4193 IOPS (target 1500) - PASS
Test PASS

Here are the results in the Raspberry Pi 4b:

Raspberry Pi Diagnostics - version 0.5
Sun Oct  4 16:11:35 2020
Test : SD Card Speed Test
Run 1
prepare-file;0;0;157538;307
seq-write;0;0;161418;315
rand-4k-write;0;0;49461;12365
rand-4k-read;48259;12064;0;0
Sequential write speed 161418 KB/sec (target 10000) - PASS
Random write speed 12365 IOPS (target 500) - PASS
Random read speed 12064 IOPS (target 1500) - PASS
Test PASS


Monday, 28 September 2020

Testing DHCP server configured for v6 only with another Raspberry Pi

I wanted to test the DHCP server installed on Raspberry Pi OS configured for v6 only as described in my recent The ultimate guide for RPD provisioning blog post. To achieve this, I used another Raspberry Pi OS directly connected back to back with a single ethernet patch cable.

First, we need a DHCPv6 client on the other Raspberry Pi OS.

pi@raspberrypi:~ $ sudo apt-get install wide-dhcpv6-client

During installation, specify the eth0 interface and also edit the following configuration file:

pi@raspberrypi:~ $ sudo nano /etc/wide-dhcpv6/dhcp6c.conf
interface eth0 {
  send ia-na 0;
};
id-assoc na 0 {
};

As IPv6 networks learned from a router advertisement, we need to install another tool besides DHCP on the server-side to enable back to back IPv6 communication over the direct ethernet patch cable:

pi@raspberrypi:~ $ sudo apt install radvd

The following config file advertises the same network configured in the previous blog post on the DHCP server:

pi@raspberrypi:~ $ sudo nano /etc/radvd.conf
interface eth0 {
    AdvSendAdvert on;
    prefix fd51:42f8:caae:d92e::/64;
};

This concludes IPv6 connectivity between the DHCP server and DHCP client via acquired IPv6 address. 

Sunday, 27 September 2020

First steps to build a cluster with ansible

As I have chosen a cluster case for my very first 2GB Raspberry Pi 4b, it was only a matter of time that I find an excuse to buy a second one. The very first challenge that I found when building a cluster is to keep the packages updated. Of course, I can log in to both of them to keep them updated, but this is easier with ansible. 

To start off, I used Raspberry Pi Imager on Debian with Raspberry Pi Desktop running on my Lenovo T480s laptop from persistent live USB to flash Raspberry Pi OS on both 32 GB SD cards. I made the installation headless by merely adding an empty file named ssh to the /boot partition before ejecting the SD cards. I have added static DHCP entries for both of them in pi-hole so that I can use names instead of IP addresses to reach them. I logged in initially to both of them to change the password and then copied my ssh keys on them.

Next, I installed ansible:

jordana@dad-laptop-ac:~ $ sudo apt install ansible

Checked version to see it installed properly:

jordana@dad-laptop-ac:~ $ ansible --version
ansible 2.7.7
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/pi/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.7.3 (default, Jul 25 2020, 13:03:44) [GCC 8.3.0]

Added both names configured for static DHCP and pi as username:  

jordana@dad-laptop-ac:~ $ sudo nano /etc/ansible/hosts
[pi]
pi4b1-eth
pi4b2-eth
[pi:vars]
ansible_user=pi

Then I created a playbook to bring all packages to the latest state:

jordana@dad-laptop-ac:~ $ nano apt.yml
---
  - hosts: pi
    tasks:
      - become: yes
        apt:
          force_apt_get: yes
          update_cache: yes
          name: "*"
          state: latest

Running the playbook I get the following. Notice that the second run did not cause change.

jordana@dad-laptop-ac:~ $ ansible-playbook apt.yml 

PLAY [pi] ******************************************************************************************************************************

TASK [Gathering Facts] *****************************************************************************************************************
ok: [pi4b1-eth]
ok: [pi4b2-eth]

TASK [apt] *****************************************************************************************************************************
changed: [pi4b2-eth]
changed: [pi4b1-eth]

PLAY RECAP *****************************************************************************************************************************
pi4b1-eth                  : ok=2    changed=1    unreachable=0    failed=0   
pi4b2-eth                  : ok=2    changed=1    unreachable=0    failed=0   

jordana@dad-laptop-ac:~ $ ansible-playbook apt.yml 

PLAY [pi] ******************************************************************************************************************************

TASK [Gathering Facts] *****************************************************************************************************************
ok: [pi4b1-eth]
ok: [pi4b2-eth]

TASK [apt] *****************************************************************************************************************************
ok: [pi4b2-eth]
ok: [pi4b1-eth]

PLAY RECAP *****************************************************************************************************************************
pi4b1-eth                  : ok=2    changed=0    unreachable=0    failed=0   
pi4b2-eth                  : ok=2    changed=0    unreachable=0    failed=0   

I have also installed ansible on the Ubuntu-20.04 I use with Windows Subsystem for Linux.

jordana@LP-AJORDAN:~$ ansible --version
ansible 2.9.6
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/jordana/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.8.2 (default, Jul 16 2020, 14:00:26) [GCC 9.3.0]

For some reason this installation worked fine without force_apt_get parameter in the apt.yml file.

This concludes the first challenge to keep packages updated on my shiny new cluster.

Monday, 21 September 2020

The ultimate guide for RPD provisioning

To boot up the RPD, we will need two services configured on the Raspberry Pi in IPv6: 1) DHCPv6 service 2) time service. To provide SW upgrade capabilities on the Raspberry Pi for the RPD, we will need a third one: TFTP service.

First let us dip our toe to the services running on Linux by listing them. For this we can use the following command:

pi@raspberrypi:~ $ sudo netstat -lp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 pi4b2.lan:47522         0.0.0.0:*               LISTEN      3501/zerotier-one  
tcp        0      0 pi4b2.lan:47523         0.0.0.0:*               LISTEN      3501/zerotier-one  
tcp        0      0 pi4b2.lan:9993          0.0.0.0:*               LISTEN      3501/zerotier-one  
tcp        0      0 localhost:9993          0.0.0.0:*               LISTEN      3501/zerotier-one  
tcp6       0      0 localhost:9993          [::]:*                  LISTEN      3501/zerotier-one  
udp        0      0 pi4b2.lan:47522         0.0.0.0:*                           3501/zerotier-one  
udp        0      0 pi4b2.lan:47523         0.0.0.0:*                           3501/zerotier-one  
udp        0      0 0.0.0.0:46103           0.0.0.0:*                           352/avahi-daemon: r
udp        0      0 0.0.0.0:bootpc          0.0.0.0:*                           692/dhcpcd          
udp        0      0 0.0.0.0:mdns            0.0.0.0:*                           352/avahi-daemon: r
udp        0      0 pi4b2.lan:9993          0.0.0.0:*                           3501/zerotier-one  
udp6       0      0 [::]:dhcpv6-client      [::]:*                              692/dhcpcd          
udp6       0      0 [::]:48271              [::]:*                              352/avahi-daemon: r
udp6       0      0 [::]:mdns               [::]:*                              352/avahi-daemon: r
raw6       0      0 [::]:ipv6-icmp          [::]:*                  7           692/dhcpcd          
Active UNIX domain sockets (only servers)
Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Path
unix  2      [ ACC ]     STREAM     LISTENING     9742     1/init               /run/systemd/journal/stdout
unix  2      [ ACC ]     STREAM     LISTENING     9763     1/init               /run/systemd/fsck.progress
unix  2      [ ACC ]     SEQPACKET  LISTENING     10330    1/init               /run/udev/control
unix  2      [ ACC ]     STREAM     LISTENING     14993    692/dhcpcd           /var/run/dhcpcd.sock
unix  2      [ ACC ]     STREAM     LISTENING     14995    692/dhcpcd           /var/run/dhcpcd.unpriv.sock
unix  2      [ ACC ]     STREAM     LISTENING     18867    852/systemd          /run/user/1000/systemd/private
unix  2      [ ACC ]     STREAM     LISTENING     13495    1/init               /run/thd.socket
unix  2      [ ACC ]     STREAM     LISTENING     18873    852/systemd          /run/user/1000/gnupg/S.dirmngr
unix  2      [ ACC ]     STREAM     LISTENING     13499    1/init               /var/run/dbus/system_bus_socket
unix  2      [ ACC ]     STREAM     LISTENING     18877    852/systemd          /run/user/1000/gnupg/S.gpg-agent.ssh
unix  2      [ ACC ]     STREAM     LISTENING     18880    852/systemd          /run/user/1000/gnupg/S.gpg-agent.extra
unix  2      [ ACC ]     STREAM     LISTENING     13504    1/init               /run/avahi-daemon/socket
unix  2      [ ACC ]     STREAM     LISTENING     18882    852/systemd          /run/user/1000/gnupg/S.gpg-agent.browser
unix  2      [ ACC ]     STREAM     LISTENING     18884    852/systemd          /run/user/1000/gnupg/S.gpg-agent
unix  2      [ ACC ]     STREAM     LISTENING     9724     1/init               /run/systemd/private

For now, please notice dhcpcd is one of the services. This service is responsible for gaining IP addresses for interfaces. It comes handy for us now because we will need to configure a static IPv6 address for the wired Gigabit so-called eth0 interface to serve the RPD with all those DHCPv6, time and TFTP services. Please connect this wired Gigabit port to a switch so that we can see the changes on the interface as we move along.
Once connected, let us first use the following command to check what IP addresses we currently have:

pi@raspberrypi:~ $ ip a
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
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether dc:a6:32:c6:4f:ee brd ff:ff:ff:ff:ff:ff
    inet 169.254.114.74/16 brd 169.254.255.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::4f1b:d468:f188:19ee/64 scope link
       valid_lft forever preferred_lft forever
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether dc:a6:32:c6:4f:ef brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.8/24 brd 192.168.1.255 scope global dynamic noprefixroute wlan0
       valid_lft 86384sec preferred_lft 75584sec
    inet6 fe80::ed25:290d:d706:8ab2/64 scope link
       valid_lft forever preferred_lft forever
4: ztks5s5bvz: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 2800 qdisc pfifo_fast state UNKNOWN group default qlen 1000
    link/ether d6:8a:40:30:e3:08 brd ff:ff:ff:ff:ff:ff
    inet 192.168.192.43/24 brd 192.168.192.255 scope global ztks5s5bvz
       valid_lft forever preferred_lft forever
    inet6 fe80::d48a:40ff:fe30:e308/64 scope link
       valid_lft forever preferred_lft forever

To add a static IPv6 address to eth0 use the following command:
 
pi@raspberrypi:~ $ sudo nano /etc/dhcpcd.conf
 
Remove the starting # from the following two lines and press Ctrl+x then Yes and Enter:
 
interface eth0
static ip6_address=fd51:42f8:caae:d92e::ff/64
 
Now let us reboot our Raspberry Pi for this configuration to take effect with the following command:
 
pi@raspberrypi:~ $ sudo reboot
 
Once the system boots up again, let us check from the terminal window again the IP addresses with the following command:
 
pi@raspberrypi:~ $ ip a
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
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether dc:a6:32:c6:4f:ee brd ff:ff:ff:ff:ff:ff
    inet 169.254.114.74/16 brd 169.254.255.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fd51:42f8:caae:d92e::ff/64 scope global noprefixroute
       valid_lft forever preferred_lft forever
    inet6 fe80::4f1b:d468:f188:19ee/64 scope link
       valid_lft forever preferred_lft forever
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether dc:a6:32:c6:4f:ef brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.8/24 brd 192.168.1.255 scope global dynamic noprefixroute wlan0
       valid_lft 85542sec preferred_lft 74742sec
    inet6 fe80::ed25:290d:d706:8ab2/64 scope link
       valid_lft forever preferred_lft forever
4: ztks5s5bvz: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 2800 qdisc pfifo_fast state UNKNOWN group default qlen 1000
    link/ether d6:8a:40:30:e3:08 brd ff:ff:ff:ff:ff:ff
    inet 192.168.192.43/24 brd 192.168.192.255 scope global ztks5s5bvz
       valid_lft forever preferred_lft forever
    inet6 fe80::d48a:40ff:fe30:e308/64 scope link
       valid_lft forever preferred_lft forever

Please notice that we have our shiny new static IPv6 address showing up under eth0 now.
 
Now we need to install a DHCP server with the following command:
 
pi@raspberrypi:~ $ sudo apt install isc-dhcp-server
 
Do not bother too much that it failed to load upon installation. We just need to configure it first with the following command:
 
pi@raspberrypi:~ $ sudo nano /etc/dhcp/dhcpd6.conf
 
Add these lines to the end of the file and press Ctrl+x then Yes and Enter:
 
option space docsis code width 2 length width 2;
option docsis.cablelabs-syslog-servers code 34 = array of ip6-address;
option docsis.time-servers code 37 = array of ip6-address;
option docsis.time-offset code 38 = signed integer 32;
option docsis.ccap-core code 61 = array of ip6-address;
option vsio.docsis code 4491 = encapsulate docsis;
option docsis.cablelabs-syslog-servers fd51:42f8:caae:d92e::ff;
option docsis.time-servers fd51:42f8:caae:d92e::ff;
option docsis.time-offset -25200;
option docsis.ccap-core fd51:42f8:caae:d92e::ff;
subnet6 fd51:42f8:caae:d92e::0/64 {
  range6 fd51:42f8:caae:d92e::fe fd51:42f8:caae:d92e::fe;
}

Finally, we need to restrict the DHCP server for IPv6 with the following configuration file:
 
pi@raspberrypi:~ $ sudo nano /etc/default/isc-dhcp-server
 
Modify this configuration file so that it looks like this then press Ctrl+x then Yes and Enter:
 
# Defaults for isc-dhcp-server (sourced by /etc/init.d/isc-dhcp-server)
 
# Path to dhcpd's config file (default: /etc/dhcp/dhcpd.conf).
#DHCPDv4_CONF=/etc/dhcp/dhcpd.conf
DHCPDv6_CONF=/etc/dhcp/dhcpd6.conf
 
# Path to dhcpd's PID file (default: /var/run/dhcpd.pid).
#DHCPDv4_PID=/var/run/dhcpd.pid
DHCPDv6_PID=/var/run/dhcpd6.pid
 
# Additional options to start dhcpd with.
#       Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead
OPTIONS="-6"
 
# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
#       Separate multiple interfaces with spaces, e.g. "eth0 eth1".
#INTERFACESv4=""
INTERFACESv6="eth0"

Now we need to restart the DHCP service with the following commands:
 
pi@raspberrypi:~ $ sudo systemctl stop isc-dhcp-server.service
pi@raspberrypi:~ $ sudo systemctl start isc-dhcp-server.service
pi@raspberrypi:~ $ sudo systemctl status isc-dhcp-server.service
isc-dhcp-server.service - LSB: DHCP server
   Loaded: loaded (/etc/init.d/isc-dhcp-server; generated)
   Active: active (running) since Tue 2020-09-22 00:38:12 BST; 6s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 2004 ExecStart=/etc/init.d/isc-dhcp-server start (code=exited, status=0/SUCCESS)
    Tasks: 1 (limit: 3862)
   CGroup: /system.slice/isc-dhcp-server.service
           └─2013 /usr/sbin/dhcpd -6 -q -cf /etc/dhcp/dhcpd6.conf eth0
 
Sep 22 00:38:10 raspberrypi systemd[1]: Starting LSB: DHCP server...
Sep 22 00:38:10 raspberrypi isc-dhcp-server[2004]: Launching IPv6 server only.
Sep 22 00:38:10 raspberrypi dhcpd[2013]: Wrote 0 NA, 0 TA, 0 PD leases to lease file.
Sep 22 00:38:10 raspberrypi dhcpd[2013]: Bound to *:547
Sep 22 00:38:10 raspberrypi dhcpd[2013]: Server starting service.
Sep 22 00:38:12 raspberrypi isc-dhcp-server[2004]: Starting ISC DHCPv6 server: dhcpd6.
Sep 22 00:38:12 raspberrypi systemd[1]: Started LSB: DHCP server.
 
We can now find dhcpv6-server in the list of services:
 
pi@raspberrypi:~ $ sudo netstat -lp | grep dhcpv6-server
udp6       0      0 [::]:dhcpv6-server      [::]:*                              654/dhcpd    

There are two more services left to configure. For the time service let us install xinetd with the following command:
 
pi@raspberrypi:~ $ sudo apt install xinetd
 
To enable time service on udp, alter disable from yes to no in the following config file and then press Ctrl+x then Yes and Enter:
 
pi@raspberrypi:~ $ sudo nano /etc/xinetd.d/time-udp
 
Bouncing xinetd will bring up time service:
 
pi@raspberrypi:~ $ sudo systemctl stop xinetd.service
pi@raspberrypi:~ $ sudo systemctl start xinetd.service
pi@raspberrypi:~ $ sudo netstat -lp | grep time
udp6       0      0 [::]:time               [::]:*                              1267/xinetd        
 
Finally, let us add TFTP service with the following command:
 
pi@raspberrypi:~ $ sudo apt install tftpd

We need to add the following configuration file:
 
pi@raspberrypi:~ $ sudo nano /etc/xinetd.d/tftp

Add these lines to this configuration file and then press Ctrl+x then Yes and Enter:
 
service tftp
{
protocol        = udp
port            = 69
socket_type     = dgram
wait            = yes
user            = nobody
server          = /usr/sbin/in.tftpd
server_args     = /tftpboot
disable         = no
}

Bouncing xinetd again will bring up tftp service:
 
pi@raspberrypi:~ $ sudo systemctl stop xinetd.service
pi@raspberrypi:~ $ sudo systemctl start xinetd.service
pi@raspberrypi:~ $ sudo netstat -lp | grep tftp
udp6       0      0 [::]:tftp               [::]:*                              1513/xinetd
 
To create default directory for tftp add these commands:
 
pi@raspberrypi:~ $ sudo mkdir /tftpboot
pi@raspberrypi:~ $ sudo chmod -R 777 /tftpboot
pi@raspberrypi:~ $ sudo chown -R nobody /tftpboot

This concludes the installation. However, isc-dhcp-server might not start automatically if wifi acquires carrier faster then eth0. To work around this issue:

pi@raspberrypi:~ $ sudo systemctl edit isc-dhcp-server.service
[Service]
ExecStartPre=/bin/sleep 10

This adds 10 seconds delay before isc-dhcp-server starts after wifi has come up. This is usually enough for eth0 also to acquire carrier.

With the courtesy of my colleague in the US, I can share a picture of this lab:



Sunday, 6 September 2020

Testing Docsis remote PHY device using DHCPv6 from Raspberry Pi (Desktop)

 I work on an RF bracket for a Docsis remote PHY device. This requires collaboration with RF engineers who have limited knowledge about computers. While the latest software version of the Docsis remote PHY device supports RF test mode that is perfect for an RF engineer, it still requires DHCPv6 to boot up properly which is a definite challenge for someone less familiar with computers.

During the lockdown, I had to have the RF bracket tested with an RF engineer, but he only had RF test equipment in his garage with an ancient laptop having a single working USB adapter. I have remotely supported him flashing Debian with Raspberry Pi Desktop on a USB stick and helped him to configure DHCPv6 using Debian with Raspberry Pi Desktop on the USB stick in live persistent mode. Almost everything worked out perfectly at the end apart from the DHCPv6 server did not start automatically at boot but had to be manually restarted. Posted the issue on Raspberry forum but received no real feedback:

https://www.raspberrypi.org/forums/viewtopic.php?f=116&t=274573

Based on this success now, I work with another RF engineer in an RF lab in California where we also need to provide DHCPv6 address for a Docsis remote PHY device. We have agreed to accomplish this with a Raspberry Pi this time so that it can stay there permanently. I will provide remote support via ssh tunnel through my free Google Cloud VM instance based on this article:

https://medium.com/jj-innovative-results/how-to-access-a-raspberry-pi-anywhere-with-reverse-ssh-and-google-cloud-platform-59b6a89501a

Sunday, 31 May 2020

Settling on ubuntu

After consulting IT support and opening a ticket it became obvious that getting my hands on a windows installer will not be easy so I decided to give ubuntu a chance on the company SSD. And I did not regret that - everything works flawlessly including native Teams desktop application, the faster than wired gigabit 160 MHz Intel AX200 wifi 6 adapter and the VNC with Remina via autostarting OpenVPN to the test lab I am using. Finally using Windows 10 in a virtual machine is giving me access to an Outlook desktop client via company Global Protect VPN that makes the experience totally complete. I have even upgraded to the newest Edge browser.

Saturday, 23 May 2020

Victims of the progress

The installation of my work custom xubuntu eventually failed with qemu on my laptop running RPD. Probably because I could not figure out how to create a VM with more than 2047 MB memory that seems to be an out of box limitation of the qemu package on RPD. With the 64GB SD card and also another 64GB UHS micro SD card the installation did not complete fully and could only boot up to runlevel 3 with upstart option as it kept missing hugepages.
Also, the mini PC freed up from its work VPN duties suffered fatally when I realised that its BIOS only lists bootable USB if formatted to NTFS and tried to change boot image BIOS setting from Windows to Android. After this change, the mini PC did not even load BIOS anymore...
But I did not give up and tried to install my work custom xubuntu burned onto a USB stick plugged into one port on my laptop to another bootable USB stick plugged into another port. After a few cycles I had to realise that I need to remove the SSD drive and use the iso image of my work custom xubuntu in the left side USB port otherwise the installer kept overwriting it. Just to be sure I have used a locked SD card in a USB reader eventually just to be sure. Also, the destination USB stick had to be ext4 formatted with GParted as in the case I created just a boot partition with fdisk it complained about missing root file system mounting point. Even in the case when the USB stricks have been plugged in the right order the installer stumbled a bit creating the necessary partitions but allowed an option that eventually made progress through the partitioning successfully.

Thursday, 21 May 2020

Applying all of it to work

Work has always been one of the most important reason to start this journey and now it is showing some return as I applied my recent learning on kvm to install some components of the SW I am working with on an SD card. I had an empty 16GB SD card and the custom ubuntu from my work system happily installed on it. I have even found a nice GUI called aqemu with which I could send ctl-alt-f1 to switch to tty1 and start deployment by sending commands via the clipboard copied from the bring-up guide. I got stuck when the 10GB bulk release had to be pulled in that clearly did not fit into the qcow2 image due to the overall 16GB size of the SD card where it resides. So I freed up the 64GB SDXC card from my video camera by shoveling its entire content on my Synology. I have also realised after some unsuccessful struggle to install 32 bit Windows desktop client of Global Protect company VPN with wine that openconnect support Global Protect protocol perfectly for my company VPN so I can ditch the remote desktop to the Windows Mini PC I used so far to get access to the bring-up guide. This also opens the possibility to explore the option to install the other custom ubuntu image on the Mini PC and learn more about the networking aspect of the virtualised world. While this Mini PC only has an Atom processor but that has two cores with 2 threads on each and have hardware support for VT-x virtualization so have some hope that the company SW can be installed on it. More about it later.

Saturday, 16 May 2020

[UPDATED] Second try with Ubuntu

My first try with Ubuntu failed as its live USB ISO did not contain a persistent option. As I learned about qemu more recently the idea has given itself to apply it to give a second try with Ubuntu. While I do not really have enough disk space on my nice&neat little Sandisk Cruzer Fit only 32GB I still thought I give it a try. Moving ISO files across was painful. While using bitorrent on Synology did help to get the image in the house when I downloaded it to the Sandisk it was painfully slow. Nevermind it was high time to get my next gadget from amazon anyway so a 128GB SSD in nice&neat little USB 3.0 form factor is on its way now supporting over 200MB/s transfer rate.

But back to the Ubuntu try: I found this article https://linuxhint.com/install_qemu_debian/ that focused on hardware acceleration so I thought I follow this one but with Ubuntu instead of Alpine. It turned out that the maximum memory that can be used is 2GB and the minimum disk space needed is 9GB so I used these parameters and started to install the 20.04 LTS with minimum configuration but it kept halting. Maybe I better wait for the new USB key with this...

[UPDATE]
As it did not install even overnight I checked again what is behind 200MB/s headline number and found a lot of misery with write speed in the reviews so I cancelled the new card and thought about a new strategy of using a separated SD card in the SD card slot in my laptop to install Ubuntu on it. This went reasonably fast so the next step on getting familiar with Ubuntu has been accomplished.

[FIXED] Burn-n-boot pihole

I think I found the ultimate solution for making my own custom burn-n-boot Raspbian image with fully fledged pihole running on it.

Wrote Raspbian Lite with Imager this time on the SD card. Then installed qemu-system-arm on my live USB Debian and downloaded ready made kernel image and compiled device tree file from https://github.com/dhruvvyas90/qemu-rpi-kernel that can emulate my Raspberry Pi 1. Quick fdisk -l to find out disk name this time is /dev/sda and this single command has booted an entire virtual machine from the SD card:
sudo qemu-system-arm -M versatilepb -cpu arm1176 -m 256 -hda /dev/sda -dtb ~/Downloads/versatile-pb-buster.dtb -kernel ~/Downloads/kernel-qemu-4.19.50-buster -append 'root=/dev/sda2 panic=1' -no-reboot &
We can jump right into installing pihole:
sudo curl -sSL https://install.pi-hole.net | bash
Could configure the final static IP address and default gateway also as it will only be applied after reboot so could still pull static DHCP config file from host:
sudo scp jordana@10.0.2.2:04-pihole-static-dhcp.conf /etc/dnsmasq.d
After minimal password management shutdown the virtual machine:
passwd
pihole -a -p
sudo shutdown -h now
Dropped a new file named ssh into boot disk from File Manager before ejected it and that is it. Swapped in the new card into RPI and the family did not notice the change. Finished by expanding the file-system with raspi-config, apt update/upgrade and enabling DHCP from web interface and confirmed it is all running OK.

Friday, 15 May 2020

Burn-n-boot pihole

This post https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=231762 has made me thinking if I could burn-n-boot pihole onto a spare SD card and swap it in my RPI without the family noticing it. Since the lockdown the entire family is constantly hooked on the net so pihole has become a critical component of the peace at home.

The process was successful but not flawless. Here is my workflow with findings:
First I booted Debian with Raspberry Pi Desktop on my ThinkPad from persistent live USB.
Then started the workflow with writing newest Raspbian on an SD card with Imager.
sudo fdisk -l
gave me that the SD card is disk /dev/sda
sudo mkdir /mnt/raspbian
sudo mount /dev/sda2 /mnt/raspbian
sudo mount /dev/sda1 /mnt/raspbian/boot
sudo systemd-nspawn -D /mnt/raspbian
and here I arrived at the first hiccup:
ERROR: ld.so: object '/usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
I could get rid of this ERROR by commenting the only line in /etc/ld.so.preload that contained the shared object file that cannot open.
apt update
apt -y upgrade
there was some hiccup:
System has not been booted with systemd as init system (PID 1). Can't operate
invoke-rc.d: could not determine current runlevel
Warning: using insecure memory!
but the upgrade eventually finished.
curl -sSL https://install.pi-hole.net | bash
Here I arrived some more hiccups
[✗] Checking apt-get for upgraded packages
Kernel update detected. If the install fails, please reboot and try again
SELinux not detected
Unsupported setsockopt level=270 optname=11
Unknown host QEMU_IFLA type: 50
Unknown host QEMU_IFLA type: 51
Unknown host RTA type: 25
when I tried to set-up static IP I got kicked out with:
RTNETLINK answers: Operation not permitted
but I could see the changed static IP in /etc/dhcpcd.conf
interface eth0
        static ip_address=192.168.1.3/24
        static routers=192.168.1.1
        static domain_name_servers=8.8.8.8 8.8.4.4
so when run pihole install script again it did accept the static IP settings because:
Static IP already configured
then some more checks failed:
[✗] Check for existing repository in /etc/.pihole
[✗] Check for existing repository in /var/www/html/admin
but ultimately the install finished.
Removed webserver password and copied over dhcp config from running server:
pihole -a -p
scp jordana@192.168.1.3:/etc/dnsmasq.d/02-pihole-dhcp.conf /etc/dnsmasq.d 
scp jordana@192.168.1.3:/etc/dnsmasq.d/04-pihole-static-dhcp.conf /etc/dnsmasq.d
then finished with some user management and enabled ssh:
groups pi
useradd -m -G <all-pi-groups-comma-separated> jordana
passwd pi
passwd jordana
touch /boot/ssh
exit
finally umount and ejected the SD card
sudo umount /mnt/raspbian/boot
sudo umount /mnt/raspbian
Popping the SD card into my RPI booted nicely and I could ssh with configured user but pihole was not running.
Not sure what is wrong but only repair seemed to fix it.
pihole -r
While the repair process was reasonably fast so I only got angry looks for a minute or two I am wondering how could this workflow be improved so that pihole would just start after burn-n-boot without repair?

Tuesday, 12 May 2020

Using SSH keys and setting jordana with NOPASSWD for sudo

Last week got hooked on the advert appeared in Teams within a Chromium tab to install a native Debian desktop app for Teams. It was very appealing to combine the two so distant world of open source and proprietary. But the install was far from flawless - .deb installer did not install by simple doubleclick and from command line apt was really had to be forced. While Teams did work for a while the next real apt update got broken by the applied force during Teams install.
The easiest way to fix for me was to reset persistence in the Debian boot menu.
Using lxrandr and xbacklight/xbindkeys to reinstate my user environment was already just a finger exercise but installing openvpn from Preferences -> Add / Remove Software did not bring up the tunnel during boot even after placing config file in /etc/openvpn. Starting it manually was also further hindered as jordana user needed password for sudo so process got stopped if first invoke was trying to send it the background.

Amongst so many very interesting things the solution for setting jordana with NOPASSWD for sudo was in this article:

I have noticed that user pi already has NOPASSWD configured for sudo in /etc/sudoers.d/ so I simply copied its altered config file over for jordana user which made openvpn started flawless in the background.

This article made me also think to generate ssh keys for the connections I frequently use like the Raspberry Pi I update daily and the jumpserver for the company test lab I frequently use. This was a piece of cake with ssh-keygen and ssh-copy-id.