Setting up and using Uniden Sentinel BCDx36HP on Ubuntu 22.04 under Wine

January 15, 2024

I finally have had success in programming my Uniden BCD436 (and would probably succeed with the Uniden BCD586 if I owned one) under Wine! This has been a problem that has persisted for ages, and now it appears that things have advanced enough that it’s possible.

Installation

First, uninstall Wine: (warning: this will blow away all your Wine configs, so if you use it for more than just Sentinel, save everything first)

$ sudo apt remove wine
$ sudo apt autoremove

Next, install Wine from the WineHQ repo by adding the winehq key, adding it to your list of repos, and instaling the package (these instructions come from https://wiki.winehq.org/Ubuntu):

$ sudo wget -O /etc/apt/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key
$ sudo wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/jammy/winehq-jammy.sources
$ wine --version
wine-8.0.2

Install Sentinel. Download it from info.uniden.com and you’ll have a zip file with a name like: BCDx36HP_Sentinel_Version_2_xx_yy.zip

$ unzip BCDx36HP_Sentinel_Version_2_xx_yy.zip
$ cd BCDx36HP_Sentinel_Version_2_xx_yy
$ wine setup.exe

Follow the normal Sentinel setup procedure.

I’ve got Sentinel data files stored on my shared drive. Because of this, I had to do the following to get it reading my shared config. You probably won’t do this:

  1. Start Sentinel and download the master database.
  2. Exit Sentinel
  3. cd ~/.wine/drive_c/users/myuser/Documents/Uniden
  4. mv BCDx36HP BCDx36HP-old
  5. ln -s /my/shared/uniden/data-directory BCDx36HP (this is the directory on the SMB share that contains ActivityLog, DiscoveryLog, FavoriteLists and Profile)
  6. Start Sentinel again and confirm you can read it.
  7. Exit Sentinel

Using Sentinel

I adapted these instructions from https://wiki.radioreference.com/index.php/Sentinel_(Uniden_software)#Using_Sentinel_Under_Wine

Step 1: Connect the BCD436 to your Linux device by turning it on and selecting “Mass Storage Mode” (press the E/yes key). You’ll see it automount on Linux.

Step 2: Start Sentinel by clicking on Activities in the upper left and typing bcd, then clicking on the icon:

Step 3: Cancel out of the “Run updates” dialog. Instead, run winecfg from the terminal.

Step 4: In the dialog that comes up, click the Drives tab and then use cursor down to highlight the drive letter of the /media/ path that Ubuntu used when it automounted the drive.

Step 5: Click “Show Advanced” and change the Type from “Autodetect” to “Floppy Disk”. Press “Apply” and then “OK”.

Step 6: In Sentinel, Update -> Update Firmware…

If all went well, you should see:

Step 7. Click OK. Your firmware just got updated.

At this point you should be able to Update -> Update Master Database(HPDB). You can also make changes. Once you’ve made your changes, Scanner -> Write to Scanner…

Note: the Linux driver that talks to the scanner can be very slow when writing. You’ll have plenty of time to get a coffee, especially if you select “Force Write Full Database”. Just remember to come back in time to tell Sentinel how to handle conflicts.

Step 8: When you’re done, shut down Sentinel and then unmount the device, then eject it:

Turn the radio off. Then unplug the cable. Congratulations, you’re done.


Stop “[Application]” Is Not Responding on Ubuntu 22.04/Gnome

October 28, 2023

Since upgrading to Ubuntu 22.04, I’ve been seeing a lot more of those messages from Gnome that say:

“[Some Application]” is not responding. You may choose to wait a short while for it to continue or force the application to quit entirely.

A dialog that reads "Thunderbird Mail" is not responding. You may choose to wait a short while for it to continue or force the application to quit entirely. There are two buttons, "Force Quit" and "Wait"

Probably Ubuntu 22.04 takes up more resources on my underpowered mini PC. This error pops up when an app is not responsive for more than 5 seconds.

Luckily, that timeout is configurable. I’m not as impatient as the Gnome developers, so I adjusted mine to 15 seconds. In theory this gets stored so you don’t need to do anything to make it permanent:

$ gsettings get org.gnome.mutter check-alive-timeout
uint32 5000
$ gsettings set org.gnome.mutter check-alive-timeout 15000

You probably don’t want to set this much below 1000 or you’re going to be dealing with lots of dialogs that block the rest of the UI.


Setting up Wireguard on an OpenBSD 7.4 firewall device

October 22, 2023

It took me a little while after I set up my firewall device to set up Wireguard as a VPN. It’s probably something I should have done right away — the benefits of being able to log in from home (and block ads) while on the road is really nice.

Wireguard needs a publicly available IP or domain name. I used DuckDNS. I posted about that a while back so I won’t do it again here, but you’ll need to do that first.

Wireguard is in the kernel in 7.4. Prior releases required you to pkg_add wireguard_tools, but these days you don’t need to.

The way Wireguard works is that you generate public and private keys. Each device gets its own private key, and you share the public keys. Wireguard has tools to do that. On the OpenBSD firewall side:

# mkdir /etc/wireguard
# chmod 700 /etc/wireguard
# wg genkey > /etc/wireguard/private.key
# chmod 600 /etc/wireguard/private.key
# wg pubkey < private.key > public.key

Next, you need to generate private and public keys on each of your clients. Then set up /etc/wireguard/wg0.conf to contain the firewall’s private key and also the public keys of the client. I decided to do this on a completely different network — 172.16. I assigned individual IP addresses for each device. It’s a little more management headache, but makes it easy to delete something if I lose a device. The /etc/wireguard/wg0.conf looks like this:

[Interface]
PrivateKey = the private key from /etc/wireguard/private.key
ListenPort = 51820

[Peer]
# My first peer - a laptop
PublicKey = the public key from the laptop
AllowedIPs = 172.16.0.2

[Peer]
# My second peer - an Android device running Wireguard from F-Droid
PublicKey = the public key from the device
AllowedIPs = 172.16.0.3

# ... etc...

Obviously, on each device you have to do the reverse: specify the private key generated on device, and put the firewall’s public key in as the peer. Next, you need an /etc/hostname.wg0 to bring the network up:

inet 172.16.0.1 255.255.255.0 NONE
up
!/usr/local/bin/wg setconf wg0 /etc/wireguard/wg0.conf

Before you can go further, you need to unblock the Wireguard interface in /etc/pf.conf:

(after the lan_if macro)
vpn_if="wg0"
vpn_port="51820"

(at the end after the NAT rules)
#---------------------------------#
# WireGuard
#---------------------------------#
pass in on $vpn_if
pass in inet proto udp from any to any port $vpn_port
pass out on egress inet from ($vpn_if:network) nat-to ($ext_if:0)

From there, you can restart pf and reload the new rules and sh /etc/netstart wg0.

This post is part of a series on setting up an OpenBSD 7.4 firewall device.


Block Ad Sites and Nasties on OpenBSD 7.4

October 22, 2023

One of the benefits of building your own firewall is that you get to decide what you want to block. I’d been using a list from pgl.yoyo.org/adservers. There’s a utility called Pf-badhost that blocks evil hosts. I wanted to do a little more: block bad IPs (sorry, Cloudflare, I know you hate that) and have better control over when things get updated.

So I ultimately decided to adapt some of Pf-badhost to a few scripts I created. First, a script to get the latest list of bad hostnames from pgl.yoyo.org — grab-bad-hosts.sh:

Grabbing Bad Hostnames

#! /bin/sh
/usr/local/bin/wget -O ./pgl-adhosts.conf 'https://pgl.yoyo.org/adservers/serverlist.php?hostformat=unbound&showintro=1&mimetype=plaintext'

grep -v -f /var/unbound/etc/unbound-whitelist-ads.txt pgl-adhosts.conf > unbound-adhosts.conf
grep -f /var/unbound/etc/unbound-whitelist-ads.txt pgl-adhosts.conf > unbound-adhosts-whitelist.conf

echo "In a root shell, run:"
echo "cat unbound-adhosts.conf  > /var/unbound/etc/unbound-adhosts.conf"
echo "cat unbound-adhosts-whitelist.conf  > /var/unbound/etc/unbound-adhosts-whitelist.conf"
echo "rcctl restart unbound"
echo "(or run root-update-hosts.sh as root)"

This builds two files: /var/unbound/etc/unbound-adhosts.conf and /var/unbound/etc/unbound-adhosts-whitelists.conf based on a file I created, /var/unbound/etc/unbound-whitelist-ads.txt, which I had to add to make other users happy. /var/unbound/etc/unbound-whitelist-ads.txt looks like this:

adservice.google.com[^.]
googleadservices.com[^.]

… and I’m going to set up unbound to allow one host to have the whitelisted ads.

Grabbing Bad IPs

I used Pf-badhost as a source of places to grab bad IP addresses from. I ended up with this script, grab-bad-ips.sh:

#! /bin/sh
/usr/local/bin/wget -O ./banlist_firehol_level1 https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/firehol_level1.netset
/usr/local/bin/wget -O ./banlist_firehol_level2 https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/firehol_level2.netset
/usr/local/bin/wget -O ./banlist_binarydefence https://www.binarydefense.com/banlist.txt
/usr/local/bin/wget -O ./banlist_emergingthreats https://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt
cat ./banlist_firehol_level1 > pf-badguys.table
printf "\n">> pf-badguys.table
cat ./banlist_firehol_level2 >> pf-badguys.table
printf "\n">> pf-badguys.table
cat ./banlist_binarydefence >> pf-badguys.table
printf "\n">> pf-badguys.table
cat ./banlist_emergingthreats >> pf-badguys.table
printf "\n">> pf-badguys.table
grep '^[0-9]' pf-badguys.table | sort | uniq > pf-badguys.table.sort.uniq
mv pf-badguys.table.sort.uniq pf-badguys.table

echo "In a root shell, run:"
echo "  cat pf-badguys.table > /etc/pf-badguys.table"
echo "  pfctl -F Tables -f /etc/pf.conf"
echo "(or run root-update-ips.sh as root)"

This script creates /etc/pf-badguys.table, which I’ll plug into my PF configuration.

Configuring unbound to use the bad hosts lists

It’s not hard to have unbound import the bad hosts, which are already formatted to redirect to 127.0.0.1. Here’s a sample from /var/unbound/etc/unbound-adhosts.conf:

local-zone: "1-1ads.com" redirect
local-data: "1-1ads.com A 127.0.0.1"

unbound-adhosts-whitelist.conf looks the same, but only contains the whitelisted ad servers. After the last local-data:/local-data-ptr: pair for my network, I added the following:

        # open a hole for ad servers                                            
        # 192.168.150.180 is unblocked desktop                                   
        access-control-view: 192.168.150.180/32 adview

After my access-control: directives, I added:

#  Host addresses - spam to block                                               
#                                                                               
        include: /var/unbound/etc/unbound-adhosts.conf
        include: /var/unbound/etc/unbound-adhosts-whitelist.conf
        include: /var/unbound/etc/unbound-adhosts-local.conf

At the end of the unbound.conf file I added:

view:
        name: "adview"
        include: /var/unbound/etc/unbound-adhosts.conf
        include: /var/unbound/etc/unbound-adhosts-local.conf

Then a quick:

# unbound-checkconf
# rcctl restart unbound

… and I was blocking ad servers. I could update this in cron, but I prefer to do it manually every week or so.

Configuring PF to block the bad IP addresses

I know there’s an argument for not blocking bad IP addresses. After all, there may be legitimate sites that are hosted on the same IP address. But… so far I’ve only run into one. So I’m happy to continue blocking them. In my pf.conf, after the <martians> table, I added a <badguys> table:

table <badguys> persist file "/etc/pf-badguys.table"

Then after the block for martians, I added an equivalent for badguys:

# Block addresses in the badguys table                                          
# We use the "quick" parameter here to make this rule the last.                 
# Note that badguys might contain martians, but they get handled before
# this rule.                                                                             
block in quick on $ext_if from <badguys> to any
block return out quick on $ext_if from any to <badguys>

Then pfctl -F Tables -f /etc/pf.conf to reread the table.

This post is part of a series on setting up an OpenBSD 7.4 firewall device.


Set up networking for an OpenBSD 7.4 firewall device

October 21, 2023

Subscribe to continue reading

Subscribe to get access to the rest of this post and other subscriber-only content.


Installing OpenBSD 7.4 for a Firewall

October 15, 2023

Installing OpenBSD 7.4 was pretty simple. I followed the OpenBSD installation guide and used dd on a Linux box to write install74.img to a USB stick. Don’t use the .iso, it doesn’t boot. Then I booted off the USB stick. (You don’t have to disable UEFI.) I used a standard layout

At the time I wondered if I should install all the packages or not. I decided that maintenance would be simpler if I just went for everything, so I added all the packages including X. That turned out to be the right decision.

I used a relatively standard partitioning scheme, although I think I bumped up a few of the sizes. I probably should have bumped up X11R6 more, right now it’s at 41%:

/dev/sd0a      986M    /
/dev/sd0l      295G    /home
/dev/sd0d      291M    /tmp
/dev/sd0f      5.8G    /usr
/dev/sd0g      986M    /usr/X11R6
/dev/sd0h     19.4G    /usr/local
/dev/sd0k      5.8G    /usr/obj
/dev/sd0j      2.9G    /usr/src
/dev/sd0e     34.4G    /var

Set up doas

After installing, I set up doas ’cause I like seatbelts:

$ su
# vi /etc/doas.conf
permit persist andrewmemory as root
permit persist keepenv root as root

Install patches and packages

After that I installed patches:

$ doas syspatch
$ doas shutdown -r now

Next I installed a few useful packages:

$ doas pkg_add -i emacs mutt firefox wget 

I picked the -no_x11 version for emacs, and the normal (not gpge, not sasl, not slang) version for mutt. I’m not going to be mailing to the world from this box, just looking at local emails. I also installed Firefox, which turned out to be another good idea. It’s a lot easier to search for doc on the firewall box itself than to ssh in.

Set up mfs for /tmp

Finally, I’m paranoid about wearing out my SSD, so I set up /tmp to be mfs in /etc/fstab using the useful instructions from Solene Rapenne:

$ doas vi /etc/fstab
#f1ea06b71e2dca43.d /tmp ffs rw,nodev,nosuid 1 2
swap /tmp mfs rw,nodev,nosuid,-s=300m 0 0

… and I had to boot to single-user mode to fix up permissions for /tmp:

$ doas umount /tmp
$ doas chmod 1777 /tmp
$ doas mount /tmp

Apparently tmpfs has been removed because it’s not supported, so mfs it is. I’ve got plenty of RAM for a /tmp file system, but I have delusions of putting most of /var in its own mfs file system, so I restricted /tmp to 300M.

Once that was done, I could log into a few other machines on my network to establish fingerprints for them. I also tested X by running startx, and then firefox, and it worked.

There were some noisy beeps

By default, OpenBSD rings the bell when you mistype certain things. That was annoying other people in the house, so I had to shut those up. That took two things. In ~/.login I added:

/sbin/wsconsctl keyboard.bell.volume=0

Then, I created ~/.xsession and added:

/usr/X11R6/bin/xset b off

This post is part of a series on setting up an OpenBSD 7.4 firewall device.


Buying new hardware for an OpenBSD firewall

October 15, 2023

I knew going in that I wanted more than two ethernet ports for my OpenBSD firewall device. I had visions of multiple networks and/or a spare port that I could use when I screwed up my pf configuration. I also knew that I wanted HDMI so I could pop the firewall on my KVM switch – I’d used serial to the APU2 and that was not always wonderful. The Linux box would sometimes forget about the serial ports when they were plugged in for a while.

In the end, I got a random Intel N5105 mini-PC with four Intel ethernet ports. The HUNSN Micro Firewall Appliance, Mini PC, VPN, Router PC, Intel N5105, HUNSN RJ03, AES-NI, 4 x Intel 2.5GbE I226-V LAN, Type-C, TF, M.2 WiFi 6 Slot, Barebone, NO RAM, NO Storage, NO System was around $250 US. Add a Western Digital NVMe 500G drive and 16G of Cruical laptop RAM and I had something on which I could install a system. It’s low-powered enough that I don’t mind keeping it running 24/7, and high-powered enough that I’m not worried about it being a bottleneck.

I learned afterwards that the I226-V might potentially have a problem if you want to do 2.5G ethernet. So far, I haven’t experienced any network instability because of that.

As a belt-and-suspenders kind of thing, I bought a “silent” USB fan that sits on top of the case, just because the server room can get a little warm.

This post is part of a series on setting up an OpenBSD 7.4 firewall device.


Setting up an OpenBSD 7.4 Firewall Device

October 15, 2023

My PC Engines ALIX running the (mumble) version of OpenBSD has been a great firewall. But now that it looks like PC Engines is wrapping up, it’s time to find something new. For a while I’ve suspected that the ALIX is a little underpowered. It’s harder to find 4G CF cards these days. Plus I want something with a HDMI port so I can put it on a KVM switch and don’t need to worry about serial port speeds.

So… here’s the order of operations:

Here goes!


Setting up DuckDNS on OpenBSD

May 20, 2023

Well, that was easy. I’ve been thinking about setting up WireGuard on my firewall. That will give me ad blocking by default as well as a way into my system when I want to do something. But… that means I need a way to know what my external IP is. Dynamic DNS to the rescue!

I looked around at the providers, and DuckDNS appears to be the one whose ideology aligns most closely to mine. I went to their “Install” page and they don’t have OpenBSD. But they have something close — linux bsd cron. So I adapted their script to use OpenBSD’s ftp (which, despite its name, does https as well) instead of curl, which isn’t in the base OpenBSD distribution.

#!/bin/sh -
# Update the DNS at duckdns.org with my IP

DOMAINS="mydnshost" # comma-separated, just the hostnames, not the FQDNs
TOKEN="badcafe-dead-beef-b001-fa11ca2eba3e" # from DuckDNS

tmpfile=`/usr/bin/mktemp /tmp/duckdns.XXXXXXXXXX`
if [ $? -ne 0 ]; then
    /usr/bin/logger -i -p daemon.err "duckdns update failed, couldn't create temp file"
    exit 1
fi

/usr/bin/ftp -d -o $tmpfile "https://www.duckdns.org/update?domains=${DOMAINS}&token=${TOKEN}"
return_val=$?
url_out=`/bin/cat $tmpfile`
/bin/rm $tmpfile

if [ $return_val -eq 0 ]; then
    if [ $url_out == "OK" ]; then
        /usr/bin/logger -i -p daemon.info "duckdns update ok"
    else
        /usr/bin/logger -i -p daemon.info "duckdns update failed: $url_out"
    fi
else
    /usr/bin/logger -i -p daemon.err "duckdns update failed, returned: $return_val"
fi

Note that this doesn’t account for multiple external WANs, something I want to do in the future. It also requires IPv4. There are ip= and ipv6= parameters if you want IPv6 or a different address for different WANs.

Then all I had to do was chmod 700 and stick it in a cron file:

crontab -e
~/15 * * * * ~/duckdns/duckdns >/dev/null 2>&1

Now I can get my IP anywhere. (I’m using ~/15 instead of */15 so I don’t get 503s when everyone else decides it’s time to update.)


Logging into Ubuntu 22.04 Remote Desktop

January 16, 2023

I’d set up and configured remote desktop on my Ubuntu desktop machine, but when I tried logging in from Windows I always saw an error (“An authentication error has occurred. The token supplied to the function is invalid”):

mstsc
Error dialog reading: An authentication error has occurred. The token supplied to the function is invalid.

Luckily I found this Ubuntu bug with the workaround: use .\username instead of username because Microsoft is defaulting to something stupid.

Update: That was interesting. It works until the screen locks. Luckily there’s an extension for Gnome that lets you set up remote desktop to allow you to log in when the screen’s locked.