yojimbo

Thoughts that should have a longer lifetime than my Mastodon posts ...

2024-03-13 (Previous article: “First experiences with Konilo”)

This time I'm starting with the Nightly Snapshot tarball from (http://konilo.org/), because it's been quite a while since 2023.10 and I'm expecting a number of rough edges have been sorted out.

Less is Better

Unpacking the tarball results in a significantly cleaner and smaller set of files, and a QUICK-START.txt that points you directly to starting the system easily.

The Konilo Welcome page now only lists three commands, and some of the TUI is using colour-coding, which looks quite effective.

How is ilo.blocks built?

The snapshot doesn't contain much, besides a working ilo with several alternative VMs.

The source available via fossil has a load more, but still the blocks file comes basically “from above”. I'm getting the impression that this is because Konilo is self-hosting, and the author is dogfooding this environment; there is no “source” for the blocks, only the “current state” chosen for release.

This seems to be very consistent with the ambition of Konilo; but I'm not entirely sure it's the best way to encourage contribution from outside.

How to determine the source of a word?

This might be a generic question about Retro Forth itself (I'm not sure there's a handy way to decompile words), but seeing as the blocks store the text source for many of the words in use, finding out how to at least see the definition is good.

The catalogue viewer is handy – although it doesn't actually seem to tell you which block is currently being displayed, so you have to keep a good track of things yourself, or constantly re-assert a known state.

You can look through the list of blocks, and hope that the title texts displayed help you decide where to look next :-

a | Welcome to Konilo                                                | 0
b | (startup) (set_blocks,_load_extensions)                          | 1
c | (startup) (local_configuration)                                  | 2
d |                                                                  | 3
e |                                                                  | 4
f | (std) (constants)                                                | 5
g | (std) (s:) (constants)                                           | 6
h | (std) (c:) (classification)                                      | 7
i | (std) (c:) (conversions)                                         | 8
j | (std) (n:) (even,odd,sign,square,sqrt)                           | 9
k | (std) (v:)                                                       | 10
l | (std) (buffer:)                                                  | 11
m | (std) (s:) (begins-with,ends-with)                               | 12
n | (std) (s:) (contains/s?) (index/s)                               | 13
o | (std) (bit:) (bit-access)                                        | 14
p | (std) (b:) (byte-addressing)                                     | 15
---------------------------------------------------------------------------
1 Previous     2 Next         3 Display      4 Jump         5              
6              7              8 Rename       9 Leap         0 Quit         

But you could be a while paging through this list! Instead, use the “Leap” command to get to your destination.

In this case, I'd like to see where the manual command is getting its data from (because I want to chase down a simple typo I'd spotted). So, I think I'm supposed to Leap to the definition with the Catalogue request “9manual” ... but that doesn't seem to give me any meaningful results at all. “9catalogue” on the other hand does provide me with a bunch of related blocks :-

a | (tools:catalogue) (variables,_actions)                           | 80
b | (tools:catalogue) (actions,_continued)                           | 81
c | (tools:catalogue) (key-bindings)                                 | 82
d | (tools:catalogue) (key-bindings)                                 | 83
e | (tools:catalogue) (key-bindings)                                 | 84
f | (tools:catalogue) (hints)                                        | 85
g | (tools:catalogue) (display)                                      | 86
h | (tools:catalogue) (top-level)                                    | 87
i |                                                                  | 88
j |                                                                  | 89
k |                                                                  | 90
l |                                                                  | 91
m |                                                                  | 92
n |                                                                  | 93
o |                                                                  | 94
p | catalogue shortcuts ============================================ | 95
---------------------------------------------------------------------------
1 Previous     2 Next         3 Display      4 Jump         5              
6              7              8 Rename       9 Leap         0 Quit         

Looking at page h does indeed result in some useful source :-

a | (tools:catalogue) (top-level)                                    |
b |                                                                  |
c | :catalogue (-)                                                   |
d |   [ &catalogue:actions &catalogue:hints &catalogue:display ]     |
e |   ti:application ;                                               |
f |                                                                  |
g | &catalogue \catalog                                              |
h |                                                                  |
i |                                                                  |
j |                                                                  |
k |                                                                  |
l |                                                                  |
m |                                                                  |
n |                                                                  |
o |                                                                  |
p |                                                                  |
---------------------------------------------------------------------------
1 Previous     2 Next         3              4 Jump         5 Run          
6 Save         7 Load         8              9 Leap         0 Quit         

So now I know a little more, including that there's an alias for the catalogue command allowing me to type a little less ... catalog!

That's probably enough for now, there's a lot more hacking to do here and I'll probably have to ask the author some questions to make sure I'm getting the terminology correct for the current names of commands and concepts before writing much more :–)

2024-03-12

A while ago I spent some time getting into RetroForth, and getting very interested in the VM that runs the language as well.

I thought I'd check in with this project again recently, and discovered that Charles Childers the author has moved forwards and is now implementing a full operating system based on this work!

Konilo, the Tool for Thinking

You get the following main parts for the system :- * ilo, the virtual machine (multicore CPU with a specialist instruction set, dual stack memory model) * ilo.rom, a 256KB image with the base system image (Retro Forth) * ilo.blocks, a 16MB “filesystem” pre-loaded with utility programs, documentation & examples

You can run this on a baremetal x86, using a multiboot binary for the VM, directly on a Sparkfun Teensy 4.1, in the browser (slowly) via an x86 emulator or more usefully from a terminal on your current computer with prebuilt binaries for Linux, *BSD, macOS, Windows, also Haiku, Mac System 5,6,7 and MS-DOS. If you prefer to build from source, help yourself to C, C#, C++, Lisp, Go, Kotlin, Lua, Nim, Python, Rust, Swift ... or hand-built assembly.

This isn't a simple “here, I figured out how to build it” project. This is a “if it's going to be done portably, we need to show it being done everywhere” demonstration of skill. If you want to learn any of those other languages, the ilo VM makes a great Rosetta Stone to compare with.

Using Konilo

Despite the technical excellence of the implementation, Konilo (currently on it's second release, 2023.10) isn't all that friendly to get started with. You have to have the right files in the current working directory, and get used to REPL loops that don't identify themselves with anything as helpful as a prompt.

So grab the tarball or zip file from (http://konilo.org/), and unpack it somewhere. From a command-line, go to the top-level of the package, and execute one of the VMs from the bin directory. For my Linux PC, that's bin/ilo-amd64-linux. Hopefully you'll get the Welcome messages then you'll have a simple input line waiting for you to say something incisive. Try “bye” to immediately exit :–)

$ bin/ilo-amd64-linux 

Welcome to Konilo                                               
                                                                
 ,dPYb,                                    ,dPYb,               
 IP'`Yb                                    IP'`Yb               
 I8  8I                               gg   I8  8I               
 I8  8bgg,                            ""   I8  8'               
 I8 dP" "8    ,ggggg,   ,ggg,,ggg,    gg   I8 dP    ,ggggg,     
 I8d8bggP"   dP"  "Y8  ,8" "8P" "8,   88   I8dP    dP"  "Y8     
 I8P' "Yb,  i8'    ,8I d8   8I   8I   88   I8P    i8'    ,8I    
,d8    `Yb,,d8,   ,d8P8P    8I   Yb,_,88,_,d8b,_ ,d8,   ,d8'    
88P      Y8P"Y8888P"        8I   `Y88P""Y88P'"Y88P"Y8888P"      
                                                                
`manual` for the users guide                                    
`blocks` for help using the block editor                        
`describe name` for help on a specific word                     
`catalogue` to explore the blocks                               

The suggested commands manual, blocks and catalogue all run a console-based text user interface called (termina), which expects a screen that's at least 75 columns wide and 20 lines high (configurable, but that comes later!). The bottom 3 lines are reserved for a help section showing the current numeric selections that will work, and the convention is that 0 will quit from these at any time, returning you to the main RetroForth REPL – but there's no prompt, so you have to know where you are ...

Another gotcha is that there is nothing in the way of command history or autocomplete. If you're on a unix, and you have access to the rlwrap command, there's an autocomplete file in the source distribution (a separate download direct from the author's Fossil repository, or via a Git-based mirror on SourceHut) – see the example ri.sh script.

That's all for my initial noodling around, I hadn't noticed this project starting up but this will be fun I hope ...

Exploring Veilid Bootstrap

This is early in Veilid's history, 16 Aug 2023.

Went to https://veilid.net, read up on concepts. Joined the Discord.

“All nodes are equal” “Bootstrap nodes publish a network key” “The network key is the network Absent config, a DNS TXT query will be used to startup

At this stage in the project there is little documentation. However, there are Debian/Fedora packages for veilid-server & veilid-cli, which I started with rather than the sources.

Install veilid-server, veilid-cli. Very minimal packages, just the binaries and /etc/veilid-server/veilid-server.conf. -server install tells you how to enable systemd service.

$ veilid-server —help produces the most documentation I've seen so far ...

Specifically, you get a full config output (not sure if it's actually a valid config file yet) with velid-server —dump-config

This reveals some nice defaults, and in particular :- * network.routing_table.bootstrap: bootstrap.veilid.net

But the results from a TXT lookup there are sparse bootstrap.veilid.net. 3600 IN TXT “1,2”

So, when veilid-server starts, it sets config from commandline than starts veilidcore internally. routingtable/tasks/bootstrap.rs tells us a little more ... // Bootstrap TXT Record Format Version 0: // txtversion|envelopesupport|nodeids|hostname|dialinfoshort* // // Split bootstrap node record by '|' and then lists by ','. Example: // 0|0|VLD0:7lxDEabKqgjbe38RtBa3IZLrud84P6NhGP-pRTZzdQ|bootstrap-1.dev.veilid.net|T5150,U5150,W5150/ws

This calls txtlookup on each bootstrap hostname, so we dive into intf/native/system.rs, where txtlookup ends up calling trustdnsresolver by default, which ends up on the local system resolver. The initial TXT query retrieves a list (“1,2”), which is treated as prefixes to the hostname, giving us 1.bootstrap.veilid.net and 2.bootstrap.veilid.net (thanks Discord for helping me notice the second lookups)

1.bootstrap.veilid.net. 2345 IN TXT “0|0|VLD0:m5OY1uhPTq2VWhpYJASmzATsKTC7eZBQmyNs6tRJMmA|bootstrap-1.veilid.net|T5150,U5150,W5150/ws”

2.bootstrap.veilid.net. 3600 IN TXT “0|0|VLD0:6-FfH7TPb70U-JntwjHS7XqTCMK0lhVqPQ17dJuwlBM|bootstrap-2.veilid.net|T5150,U5150,W5150/ws”

I'm not sure why this complexity exists, rather than a simple CNAME alternative; i.e. look up the bootstrap hostname, if there are cname entries then look those up, until there are no CNAMES any more, then use TXT on the remainder.

More discussion on the Discord on this suggested that SRV records might be more appropriate; and of course this is all about the process of joining a network, not operating it, so I need to go do some more reading

2022-11-20 @yojimbo@hackers.town

TL;DR only 5% of fediverse servers publish security.txt

Introduction

There's a continuing influx of new users to the Fediverse at the moment (Oct/Nov 2022), and with them came a fair number of new infosec people.

Some of them started kicking at the tyres of the services that they were on, which has caused some concern – because of the current growth rate of users, many servers are running very tight on resources, and the admins are working hard enough just keeping things running; they don't want to have to also deal with potential outages caused by 'testing'.

There are now a few servers being set aside for testing, and this is a great resource, but they're not necessarily easy to discover.

So if you're a white-hat hacker, you should be trying to co-operate with the servers you are working on. One of the ways to do that is to consult SECURITY.TXT, an informational page described by RFC9116, and informally specified for many years before that.

This tells you who to contact with potential security issues, and can be used to describe any bounty program in place, as well as overall policies (and perhaps pleas for being left alone?)

So, I thought I'd survey how many fediverse sites actually have a SECURITY.TXT page in the first place.

Data Sources

I took lists of known servers from three different resources, * https://instances.social/ * https://fediverse.observer/ * https://fediverse.party/ combined the results to come up with a list of just over 28k domain names, and then requested /.well-known/security.txt from each one of them.

Detailed Results

Many sites didn't respond at all. This probably reflects on the “timeliness” of the list data maintained by the sources I chose; some of them actively re-survey and curate their data to make sure it is current, and others view it more as a record of servers that have been seen at some point.

Many of the sites responded with a clean 404 status code, indicating that they simply don't have the page at all.

Some of the sites responded with content (a 200 status code), but the content wasn't security.txt, it was some other default content from the site instead.

On my initial run through the servers, I ran out of inodes as I got to sites starting with 'm' :–) and had to quickly pause the job, clean up, and resume. And curl was refusing to connect to sites with 'invalid' certificates. So I'm sure I missed a few original data points. Sadly this doesn't seem to matter because the overall picture is pretty sad ...

28805 queries made, 20526 did not provide a response.

  • 8279 valid responses
  • 5520 “404”s
  • 1617 “200 OK”
  • 437 “500”-series
  • 338 redirects – I didn't ask curl to follow redirects

Of the 1617 “200 OK” responses, only 664 provided a Contact value ... although 217 of those were 'info@frendi.ca', so I'm excluding them to leave only 447. It's notable that 208 of these were actually PeerTube instances, too, with what looks like an automatically-generated file containing the site admin's address as well as the project's central reporting details, so well done PeerTube.

My final result therefore is that only 447 valid security.txt files were found in over 8000 servers, which is an approximately 5% hit rate.

Perhaps we should clean this up before complaining about white-hat activity?

Passwords are so last century ... there are two main replacements that you should consider instead, “passphrases” that are intended for you to remember and type in manually, and “password manager passwords”, which you will never type in yourself, instead relying on a specialist password manager application to copy/paste for you.

Password managers are great at coming up with high-entropy sequences of characters that you might be able to manually enter, but you're really not supposed to do so. dXD2cwb%xRm^3W^Qz2Sby3k!FhYZ^GX9 is a fantastic password (well, not now I've published it!) but you're not going to be able to remember it or type it reliably. If you can rely on a password manager application to be around whenever you want to use this, it's a great method to use.

But some things you just have to remember and type for yourself. The passphrase you use to open the password manager itself, for example. Perhaps you have another authentication action you perform a few times a day – sudo perhaps for the unix users. The login to your computer that you need to use on the screen lock whenever you leave the desk for a coffee ... a limited set of these are great candidates for being typed in by hand, and that sort of gibberish above just isn't going to work.

So instead we have passphrases – sequences of words, not sentences. Not lyrics to your favourite songs, not quotations from books, not the names of the players in the football team you support ... but a random sequence of unrelated words that were created by your password manager for you!

Here the number of words that you choose to use is the important factor, not the overall length of the thing. 6 or 7 words seems to be the current (2021) recommendation, but for things that you deem to be more critical or especially long-lived, 9 is a sensible max. Ideally this is something that you're going to be using several times per week, too.

But how easy is it to remember 9 unrelated words? This is what a few examples look like :-

  • barista diffusion reflux armful strife zigzagged security shelter backlash
  • nemesis domestic remover wool calzone wrongful enjoyer recolor voice
  • capable anatomy footman squiggly anew goldfish thirteen headway flattery

How are you going to remember all that?

Well, to start with, some unexpected advice ... as long as you don't work in a maximum security environment ...

Writing the phrase down on a small piece of paper that you store somewhere secure (like with your credit cards), while you're getting used to using it and remembering it, is a good idea! Just remember to securely destroy it when you don't need it any more, and of course don't write any other identifying information on there.

But there's another way to store a reminder for a passphrase too – turn the words into a series of icons or pictures, and use those to remind yourself of what the actual words are. The advantage here is that any given image that you choose could represent dozens of different words, depending on how they're interpreted, and no-one will be able to work out the actual passphrase directly. Have you ever played Pictionary?

This means that the reminder image could be somewhere less secure than your wallet – and therefore somewhere a little more useable. If you use a paper notebook, perhaps inside the front cover ... it's still somewhere relatively secure.

A great source of simple icons is https://thenounprojectcom/ but honestly any images you get from a search engine would work well too.

So let's take a new passphrase, only 5 words this time for brevity, and see what we can come up with ...

That's not a bad selection of icons! You can probably hand-draw a version of these onto a notebook quite quickly, and when you look at them later they help to remind you of the passphrase ...

Let's try another longer one ... can you work out what this set of images is for?

Some of the words in that passphrase didn't provide a direct search result, so I substituted some other related words in order to get a useable image. This is pretty much the point – these images are a reminder to me because I'm the one that did the work to choose them. If you want to hand-draw them, even if you're no artist like me, it'll still be effective, and you can change details to suit what makes sense to you ...

If you pick your own images to use for the words in your passphrase, you'll find them to be a very effective and reasonably safe reminder to use!

(Skip to the TL;DR section below if you just want the shortest list of commands)

I have a decent spec gaming PC (NVidia GeForce GTX 970 for the graphics card) that's been running Windows 10 for the last few years, since I started playing Elite:Dangerous. But recently the SSD C: started to die, and I switched over to a new drive with Ubuntu 20.10 on it instead. Any day that I don't have to run Windows is a good day.

I found some instructions on running E:D from Steam, using protontricks and launching via Lutris, and they worked! But I'm a bit unusual and have several E:D accounts; only one is on Steam, and I wanted to follow the pattern I'd had previously, with multiple copies of the EDLauncher authenticated to different accounts, but all running from the same single installed copy of Elite.

I tried to generalise the Steam version but in the process broke everything ... so I decided to start again. This time, I was going to try to understand what every step was meant to achieve, as much as I could ...

And just as a warning here – I did all this on my live OS, so there might be some steps I've missed, because I didn't realise pre-requisites were already installed from my earlier experiments. I'd like to rerun these instructions on a new clean install of Ubuntu, but right now I'm just wanting to get into the cockpit ...

Just WINE

I installed Wine 6.6 via the winehq-devel package from WineHQ's Ubuntu repository. I'd also had some other versions installed (notably 6.5) but had been careful to avoid them by careful use of $PATH.

I set WINEPREFIX to point to a new empty directory ($HOME/EDwine), and ran winecfg. This builds & populates a minimal Windows directory structure in $HOME/EDwine, 1.4GB of data, and then presents a Windows-style config box. You don't need to make any changes in there, but have a look around and see what it's up to. In my case, it was set for Windows 7 and to send audio through pulseaudio, which was fine.

The Elite Installer

I grabbed a copy of the EliteDangerous-Client-Installer.exe from my account's 'Downloads' on the Frontier store. There's probably nothing unique or personalised about that file, we probably all get the same one.

Running it directly under Wine was straightforward, and resulted in lots of components like the VC++ Redistributable and DX9 being installed into my minimal Windows filesystem. IIRC it suggested that I 'reboot Windows' so I ran wineboot instead.

EDLaunch

Now we get to the bits where things needed tweaking. EDLaunch.exe needs the right version of the Mono run-time to be present, to provide the things that real Windows gets from the .NET Framework. The version I used came via a protontricks page discussing support for E:D under Steam, and is just the default 6.1.1 version with a couple of small helpful tweaks – https://github.com/redmcg/wine-mono/releases/tag/wine-mono-6.1.1_ED

This is an MSI file, and therefore you install it with the Windows tool msiexec :- wine msiexec /i ...path/to/wine-mono-6.1.1_ED.msi

Now the Launcher will start – but it can't render any of the GalNet News or Frontier Store adverts because there's no web browser components available. Wine will prompt for your permission to install Gecko – say yes if you want; I don't think you strictly need it, but the Launcher looks more normal if you do!

You will need to log in with your CMDR's Frontier account now. It'll work as long as you remember your credentials!

You might also get the Hardware Reporter popping up, which is a debug reporting tool. Cancel it, because Frontier obviously don't support the game being played under Wine or directly on Linux, and can't do anything with your reports anyway.

Pressing PLAY ... but not yet!

At this stage, pressing PLAY will launch the actual game. However, this is where we'll start running into problems with the efficiency of DirectX running under Wine, and any complications with your actual video card drivers.

I had installed the proprietary nvidia-driver-450 previously, this isn't perfect (I occasionally see corrupted blocks on the screen after sleeping the machine, for example, but a simple move or redraw fixes them) but it's probably the best option for my card. Obviously many of you will have different video cards, and will need different drivers, but I don't think it is going to make a difference here ... as long as you have an efficient 3D driver for your card that exposes a decent API it shouldn't matter what it is.

But Wine running DX9 isn't going to know about this, as far as I can see. If you run the game, the 3D graphics will probably be CPU bound, and I ended up crashing my machine a few times. Going through the initial shader generation took over 30 minutes, too, which isn't helpful!

Vulkan

So, I installed Vulkan into the Linux machine. This is an alternative API to DirectX, that's known to give better performance, and as I'm installing it on the Linux side, it will be aware of the NVidia drivers. This doesn't help us completely yet, but ...

sudo apt install libvulkan1 libvulkan-dev vulkan-utils

DXVK

The next part of the job is to install DXVK into the Windows environment. This tool translates the DX9 requests that Elite makes within Windows into Vulkan requests that Linux knows how to answer efficiently.

(I've also heard that it's very good at doing the same thing in a pure Windows environment, speeding up Windows games trying to use DirectX by diverting their requests to the more efficient Vulkan API)

I went to https://github.com/doitsujin/dxvk/releases and grabbed version 1.8.1, unpacked the tar file and executed the setup script under Wine

wine ...path/to/dxvk-1.8.1/setup_dxvk.sh install

You can run winecfg again at this point, and you'll see overrides in the Libraries section, with various DirectX libraries now provided by 'native', which basically means the DXVK tools you just installed.

Success, but still some issues

At this point, pressing PLAY will launch the final game executable, that will make DX9 calls for 3D graphics when you actually enter the cockpit. DXVK will divert those calls to Linux's libvulkan, and from there to the NVidia driver, efficiently.

Now, I still had lots of problems and crashes, when trying to get to Fullscreen or Borderless setups. If you set a resolution & the game crashes before switching back, you may need to find Elite's DisplaySettings.xml file (in $WINEPREFIX/drive_c/users//Local Settings/Application Data/Frontier Developments/Elite Dangerous/Options/Graphics/) and change the FullScreen value back to 0 for 'windowed', and also perhaps the ScreenWidth and ScreenHeight values too.

However, after an actual reboot of Linux (which might have made some difference to the order things were loaded in) and a couple more retries of the Graphics settings in-game, I now seem to have a stable Borderless 1920x1080 display with Ultra settings.

All I need to do now is to remap my HOTAS and I can fly free once more!

o7 Commanders!

CMDR Yojimbosan, Radio Sidewinder 📻🐍

TL;DR

  • nvidia-driver-450 for my GeForce GTX 970
  • apt install libvulkan1 libvulkan-dev vulkan-utils
  • Wine 6.6
  • wine setup_dxvk.sh install
  • wine msiexec /i wine-mono-6.1.1_ED.msi
  • wine EliteDangerous-Client-Installer.exe
  • wine "$WINEPREFIX/drive_c/Program Files (x86)/Frontier/EDLaunch/EDLaunch.exe"
  • Optionally allow Wine to install Gecko
  • PLAY Elite:Dangerous!

Sometimes I want to access a resource that's been GeoIP blocked, and I'm not in the right address range. But I have ssh access to a server that is in the right range ...

But that server doesn't run a proxy open to the world, and I'm not going to want to install extra software in there anyway, and it doesn't have a build environment for users ...

In comes sshuttle, have a look at the docs on https://sshuttle.readthedocs.io/en/stable/index.html ...

Overview As far as I know, sshuttle is the only program that solves the following common case: Your client machine (or router) is Linux, MacOS, FreeBSD, OpenBSD or pfSense. You have access to a remote network via ssh. You don’t necessarily have admin access on the remote network. The remote network has no VPN, or only stupid/complex VPN protocols (IPsec, PPTP, etc). Or maybe you are the admin and you just got frustrated with the awful state of VPN tools. You don’t want to create an ssh port forward for every single host/port on the remote network. You hate openssh’s port forwarding because it’s randomly slow and/or stupid. You can’t use openssh’s PermitTunnel feature because it’s disabled by default on openssh servers; plus it does TCP-over-TCP, which has terrible performance (see below).

I have a macOS client machine (sshuttle is available in Homebrew at least), and a remote unix box. I want to “just make this one thing work” and then switch it off ...

  • Access website resource, receive “This content is not available in your location”.
  • sudo sshuttle -e 'ssh -i /Users/jim/.ssh/id_rsa' -r jim@remote.server 0/0
  • Refresh page
  • Profit??

Once “the Internet” discovers a new SMTP service, it will be hammered by the spammers' botnets.

History Lesson

In the Old Times, every email was wanted, and every connection that was made was precious. Even spam, which was invented in 1978 (by a salesman). Then in 1994, large-scale spam was invented (by a lawyer, of course; because there were no laws on the subject, no laws were being broken) ... and by 1996 the idea of 'reputation' for a server was developed and the first blacklists of IP addresses were developed.

Of course, as any infosec practitioner should be able to tell you, maintaining blacklists is fundamentally impractical. Unfortunately for the Internet, maintaining whitelists of trusted senders was also impractical, as more and more companies sprang up on the Internet running their own mailservers.

Some of these new mailservers were configured in the old default co-operative manner – they didn't care about where a message came from, they only cared about trying to deliver it. This original position was no longer tenable, and became shamed as an “Open Relay”, and this damaged their reputation so that no-one else accepted their messages ... and when companies reputations are threatened, they sometimes fight back. Some of the blacklist operators went out of business as a result.

In the early 2000s, email content analysis was an increasingly popular approach, but did not put an end to the rising tides of spam. Laws were passed, and enforcement in many countries caught up with some egregious offenders; but as spam is effectively free to send, and some users still receive, read and interact with it (for a multitude of reasons), it continues. I'm not going to discuss content analysis here, we don't have time for it.

As we move into the early 2020s, the techniques for sending spam have changed from abusing the pre-existing and broadly legitimate email infrastructures, to sending via 'botnets' – vast collections of computers and other internet-connected devices that have been compromised by attackers and without the real owners' permissions are used to attack the rest of the Internet.

The other main sending technique is more invidious – email services belonging to real people are compromised, generally via phishing. Then the compromised accounts are used to send outbound email – sometimes in a targeted fashion to existing contacts of the user, but also sometimes just a large-scale attack on un-related destinations.

Types of spam

A non-exhaustive selection of spam types ...

  • Selling products
    • Legal products – this is “marketing”, and is where spam started. Lots of spam advertises porn websites that are themselves legal.
    • Illegal products – in the USA, this is often pharmaceuticals and oddly enough the 'companies' selling the drugs often provide excellent customer service – even if its just to prevent complaints that the credit card companies might find out about!
  • Malware
    • “Virus” propagation
  • Exploitation of the user
    • Phishing – steal the user's credentials
    • 'Advance-fee' scams (e.g. the 'Nigerian 419', romance scams, iTunes cards, etc)
    • Vanity publications – 'fake' Diplomas, pay-to-publish presses, directory listings
    • Financial fraud – fake invoices, traffic tickets, etc

Many people are somewhat wary of email coming from an unknown sender, but conversely much more trusting of email that claims to come from an existing correspondent. With the use of compromised accounts for sending email, the trust mechanism is even easier exploit.

Techniques for defence

IP blacklisting / reputation scoring

Blacklisting IP addresses was discussed above, and attempts to enumerate 'known to be bad' sources. Unfortunately this doesn't help you with 'not yet known' sources – although the absence of a 'known to be good' signal might sound like it is helpful.

However, reputation lists suffer from some issues. The range of IP addresses is large for IPv4, and immense for IPv6. Therefore your blacklist can grow to unmanageable size very quickly, and you're left considering when you can remove entries from it, which only increases the size of the 'not yet known' category.

Ideally, your blacklist should be a co-operative effort with other people listing IPs that they have found to be bad, in order to reduce the 'not yet known' group. In practice, commercial providers running anti-malware services aggregate their observations and create these lists, but they tend not to sell them independently from their services.

And the whitelist approach has some deficiencies, which only SPF has attempted to allay; one unexpected problem is that so many companies have outsourced their email handling to a small list of global suppliers, and “everyone is using gmail” means that you have to assume that some compromised accounts will be sending spam from the very sources that you wanted to whitelist.

It ends up being a bit like the Battle of Wits from The Princess Bride ...

All I have to do is divine from what I know of your IP address. Are you the sort of person who would send spam from his own server, or from his enemy's? Now, a clever man would send the spam from his own server, because he would know that only a great fool would accept a connection from an unknown sender. I'm not a great fool, so I can clearly not accept the IP address in front of you. But you must have known I was not a great fool; you would have counted on it, so I can clearly not accept the IP address in front of me.

IP greylisting

It has been observed that the software used by botnets to send email doesn't tend to have the same approach to 'reliability' as a normal mailserver – if there is a problem in delivery, botnets tend to just assume the worst and move on to the next target, whereas a legitimate email server will hang on to the message and retry repeatedly over time, giving the far end the opportunity to fix their presumably broken servers.

As such, if you start every conversation with a previously unseen server with an immediate disconnection, you are relying on legitimate mailservers to retry later (when you will accept their connection) and on botnets to give up on you and not come back.

There are two failures associated with this – large services like gmail maintain a pool of many outbound email servers, and the next retry will probably not come from the same IP address anyway. So you have to reject your way through most of their servers before any get accepted, and if your greylist list is itself time-bounded (to prevent it growing uncontrollably) you might never be able to reliably accept email from such a source.

The other failure is that although that one single message might have been avoided, the botnet operators simply don't care, and your email address will stay on their lists, and they'll still attempt all their other deliveries to you anyway.

The final issue affects everyone – timeliness of delivery. Greylisting doesn't allow you to specify when a message should be retried, it is up to the sending server. Many people are getting used to the idea that email is fast – go to a website, fail to login, fill in the 'forgotten password' form, receive the email with the link to re-enable access ... wait. Retry. Wait again. Curse. Go do something else ... and eventually the reset email turns up, but you're busy now with a different task ... this time-scale isn't controllable by you, and the sending server doesn't tell you what it will be doing. The users suffer.

SPF, DKIM, DMARC, DNSSEC

These technologies all try to provide methods to 'prove' that a given connection is legitimate, and that you as the receiving server should accept the message they represent. They all need a form of mutually-agreed “authority”, and in this case they rely on the Domain Name System, which seems like a reasonable decision, because without the DNS you probably aren't able to understand email addresses anyway. But with the full 'commercial' or 'criminal' value of email being established by the amount of spam there is in the world, you need to make sure that the data in your DNS entry is secure against tampering, and for that you need DNSSEC. But uptake of DNSSEC over the past 6 years hasn't been terribly widespread, so you can't take a position to reject email that doesn't rely on it being present ...

And they're all basically forms of content analysis, so they're out-of-scope for this blog post, which is long enough already!

Conclusions so far ...

Because there is so much spam being sent, an email server needs low-cost techniques to reduce as much of the load as possible. Rejecting a connection to your email server before you have to process the content is valuable.

IP reputation lists are mostly commercial now, but only available if you use the associated product to handle your email.

IP Greylisting is still reasonably effective, but burdens the end-user with unpredictable delays to inbound messages.

Effectiveness – based on my observations running two large email sites over the last 10 years or so, both techniques are broadly 80% effective, but it is difficult combining anything with a commercial product without increasing complexity.

There seems to be some increasing push against CAPS-LOCK in the mainstream, on all those default keyboards it takes up so much real-estate for so little return.

On my WhiteFox keyboard, I've removed CAPS-LOCK completely, and returned to the old Sun3 keyboard use of Control in that position. I've used the keyboard to remap right-fn/control to toggle the lock, but I was interested to try the same mechanism as iOS/Android have for on-screen keyboards, where double-tapping SHIFT locks it in place (and here you can start the discussion about the differences between SHIFT-LOCK and CAPS-LOCK if you want!)

I couldn't find any mechanism in Kiibohd to do what I wanted; I can set a macro for "[ LS+LS ] => [ CAPSLK ]" which works if I hold the left-SHIFT down long enough for key repeat to kick in, but not for "[ [LS] , [LS] ] => [ CAPSLK ]" – its a valid macro but doesn't seem to trigger.

So I ended up looking at Karabiner-Elements (free software, public domain using https://unlicense.org) (https://pqrs.org/osx/karabiner/index.html) as yet another helper program to run at startup :–) This does allow a “complex modification”, but doesn't help you with the UI to create your own, instead offering a “download examples from our website” process. However, the long and short of it is that this program will read $HOME/.config/karabiner/assets/complex_modifications/ at startup, and any valid json file in there is available for use (not automatically enabled).

So I did the decent thing and copied someone else's script first; “Double tab left_command to become left_control”, (https://pqrs.org/osx/karabiner/complex_modifications/json/double_tap_cmd_to_ctrl.json), and then replaced left_command with left_shift and left_control with caps_lock ... reformatted the file for clarity, restarted Karabiner, enabled the new rule, and enjoyed the results!

{
  "title": "Double left_shift toggles caps_lock",
  "rules": [
    {
      "description": "Double tapping left_shift toggles the caps_lock function. Useful for keyboards without an original caps_lock, or people who are more used to the touchscreen/iOS keyboard paradigm.",
      "manipulators": [
        {
          "conditions": [ { "name": "left_shift pressed", "type": "variable_if", "value": 1 } ],
          "from": { "key_code": "left_shift", "modifiers": { "optional": [ "any" ] } },
          "to": [ { "key_code": "caps_lock" } ],
          "type": "basic"
        },
        {
          "from": { "key_code": "left_shift", "modifiers": { "optional": [ "any" ] } },
          "to": [ { "set_variable": { "name": "left_shift pressed", "value": 1 } }, { "key_code": "left_shift" } ],
          "to_delayed_action": {
            "to_if_canceled": [ { "set_variable": { "name": "left_shift pressed", "value": 0 } } ],
            "to_if_invoked":  [ { "set_variable": { "name": "left_shift pressed", "value": 0 } } ]
          },
          "type": "basic"
        } ]
    } ] }

Purplecon 2019 laura bell, security confessions of a small country, https://purplecon.nz/talks#laura-bell, https://www.youtube.com/watch?v=k-cM5tBkwwk&list=PLS45xFo74VF546tbfXXtKDO03cVrAalM6&index=10&t=0s

we live in a small country. while geographically we're not a pip squeek, in terms of population we're really rather adorable. so how does being a small country affect our approach to security and how can we learn to love our little island thinking and use it as a superpower.

  • Not a fan of large USian frameworks like NIST, because most of NZ is too small & generalist to fit, and has different targets/adversaries
  • figure.nz is good for interesting data
  • most of our businesses don't have a traditional “polite” white collar office environment, they literally work in the field
  • we have more inherent trust, and less defensive responses
  • go to https://opensecurity.nz/ to share NZ-sized solutions