Email OAuth2 Proxy

Microsoft Screws Their Users… Again…

 

Desktop Outlook Banned From Outlook.com and Hotmail.com POP3

Microsoft had stopped allowing users of their premium Outlook desktop product (versus the useless, neutered “Outlook” wannabe bloatware “Outlook for Windows” included force installed in Windows 11) to access their “free” @hotmail.com and @outlook.com emails via POP3 and SMTP (secured or not), forcing everyone to use effectively use IMAP mode (links here and here, backup here).

Leaving discussions over any reasons (e.g. financial greed trying to force clueless desktop Outlook + “free” MS email-using people to pay for more storage) and the sheer stupidity of forcing this down Outlook users’ throats (against, say, everyone else like those using Thunderbird or other third-party email clients) aside, I had simply left this aside, relying on my trusty K-9 Mail on Android to access any emails on these “throw-away” accounts…

Unfortunately, there were a few emails (mainly shopping-related receipts) that I wanted to keep – so once again, I had to roll-up my sleeves and fix shit Microsoft breaks get things working…

Google search basically found me Email OAUTH2 Proxy nearly immediately… Attempts at simply using the Docker image did not go so smoothly, so I ended up using pipx and did a “bare metal” install..

 

Trying To Understand/Explain Things

Furthermore, I found the author’s README.md hard to understand, so I decided to whip up my “own” documentation, based more around an intended outcome (that may require multiple switches/options used together), than say, explaining individual switches.

Since some explanation sections covers multiple points, I have used separate multiple sub-section headers denoting what/which point/s a singular section would resolve/be relevant to/answer.

 

OAUTH2 Client_ID and Microsoft

For the “free” @outlook.com and @hotmail.com services (it’s never free – you pay with your information), the bastards people at Microsoft have disabled the use of custom clients (unless you jump through a lot of hoops or pay a lot of money). Therefore, this configuration uses the  client_id of Thunderbird’s public client_id (i.e. the proxy is identifying itself, during OAUTH2 token generation, that it is “a Thunderbird email client”).

 

Headless Mode

This configuration runs “headless” (i.e. --no-gui) and as a background service (i.e. no manual input interaction) with all console output pushed to a log file. There are considerations to be aware of due to the latter point – refer to the section “New Accounts and OAUTH2 Token Generation“.

Refer to * footnote.

 

Single Domain Configuration

Wildcard Mode

Adding Users Semi-Automatically

To prevent me from having to manually create and repeat configuration snippets for every account, and also minimise the ports count (i.e. one port per domain and service vs. one for each account and service), I configured emailproxy to use wildcards per domain (i.e. allow_catch_all_accounts), allowing me to configure each server type (and service port), where any attempts to log in with a here-to-fore unknown email address (on said domain), or unknown password (refer to ‘How EmailProxy Determins An Account as “New”‘) would trigger the OAUTH2 token generation ceremony.

Refer to * footnote.

 

New Accounts and OAUTH2 Token Generation

Disabling “ANY” User Creation

Any manual actions required of the OAUTH2 token generation ceremony (like copying the temporary authentication URL for actual browser-based authentication then “pasting” the token as input) has to be done only in interactive mode (i.e. run the email-oauth2-proxy-manual.sh script). By virtue of this point, not just anyone, because of your use of “wildcard” domain, can use/abuse your proxy.

  • stop  the service
    • systemctl stop emailoauth2proxy
  • run the script interactively in the foreground
    • /opt/emailproxy/email-oauth2-proxy-manual.sh
  • run the email client with the “new” account, using a complex password (that has to be re-used for this account henceforth)
    • copy the authentication URL and access using standard browser with no existing logged in sessions for said OAUTH2 domain (e.g. use “incognito mode”)
    • run through the authentication process
      • it will end in a redirect to “http://localhost:8080” with a 404 – this is expected
      • copy the token at the end of the URL and paste it back as input, to the running emailproxy process
  • test access again, once complete, (re)start the service
    • systemctl start emailoauth2proxy

*Because of the out-of-band authentication and no HTTP interface of emailproxy, the process can only be, at best, semi-automated. i.e. You will need to execute any new OAUTH2 token generation process from the server directly.

 

Disabling Auto Force New Token Generation

Separating Credentials Best Practice

Enforcing “Basic/Simple” Authentication

How EmailProxy Determines An Account Is “New”

Since --cache-store specifies a separate file, any actual accounts’ tokens and other (copied) settings (from the “wildcard” source service) will be stored in said separate file, encrypted by the initial password used during OAUTH2 token generation. I consider this “best practice” as I only need to review said file for changes.

By default (i.e. “delete_account_token_on_password_error = True“), emailproxy assumes any failure to decrypt any existing data (or finds missing data) from individual account sections means (re-)triggering a new OAUTH2 token generation ceremony/process.

By using “delete_account_token_on_password_error = False“, any failure in decrypting encrypted data of the account would not (re-)trigger a new OAUTH2 token generation ceremony/process, although missing data, or if the account section was completely missing (i.e. new), the OAUTH2 token generation ceremony/process would still be triggered (and correctly so). This acts as a sort of “basic/simple” security check – not anyone can just attempt to use your generated token and get access to your email – only when attempting to authenticate with the same password used during the initial OAUTH2 token generation ceremony/process will the client be successful.

 

Continue reading

Customising CyberChef…

So, in the need to run some Base64 encoding + decoding using local HTML files and modern browser-based JS, I came across CyberChef

Asking Google’s “AI Mode” (even the “Pro” version) to provide instructions to strip the files down to the basic (e.g. no bloat from Tesseract OCR files or other operations/modules not needed excepting “To Base64” and “From Base64” operations) was an exercise in frustration… With “instructions” from deleting .mjs operation files from source tree, to editing the src/core/config/scripts/generateConfig.mjs (in truth, only one or the other was required – along with some other steps), to attempting hard-code edits on webpack.config.js.

None of that worked correctly – No HTML was produced at the end due to some compilation error.

Fortunately, it pointed me in the right direction, and I finally managed to “shrink” my build for easy transfer, down from the hefty 70+MB .zip file…

Continue reading

Nested Partitions grub-update Mess…

Having imaged an old MBR-based partitioned disk to a VHD and back to bare metal on a now UEFI, GPT-based NVME SSD, update-grup was complaining every time:

# update-grub
Sourcing file `/etc/default/grub'
Generating grub configuration file ...
grub-probe: warning: Discarding improperly nested partition (hostdisk//dev/nvme0n1,gpt2,msdos1).
grub-probe: warning: Discarding improperly nested partition (hostdisk//dev/nvme0n1,gpt2,msdos2).
grub-probe: warning: Discarding improperly nested partition (hostdisk//dev/nvme0n1,gpt2,msdos3).
grub-probe: warning: Discarding improperly nested partition (hostdisk//dev/nvme0n1,gpt2,msdos4).

<above 4 lines repeats 11 times>

/usr/sbin/grub-probe: warning: Discarding improperly nested partition (hostdisk//dev/nvme0n1,gpt2,msdos1).
/usr/sbin/grub-probe: warning: Discarding improperly nested partition (hostdisk//dev/nvme0n1,gpt2,msdos2).
/usr/sbin/grub-probe: warning: Discarding improperly nested partition (hostdisk//dev/nvme0n1,gpt2,msdos3).
/usr/sbin/grub-probe: warning: Discarding improperly nested partition (hostdisk//dev/nvme0n1,gpt2,msdos4).

<above 4 lines repeats 29 times>

Found linux image: /boot/vmlinuz-6.17.0-22-generic
Found initrd image: /boot/initrd.img-6.17.0-22-generic
/usr/sbin/grub-probe: warning: Discarding improperly nested partition (hostdisk//dev/nvme0n1,gpt2,msdos1).
/usr/sbin/grub-probe: warning: Discarding improperly nested partition (hostdisk//dev/nvme0n1,gpt2,msdos2).
/usr/sbin/grub-probe: warning: Discarding improperly nested partition (hostdisk//dev/nvme0n1,gpt2,msdos3).
/usr/sbin/grub-probe: warning: Discarding improperly nested partition (hostdisk//dev/nvme0n1,gpt2,msdos4).

<above 4 lines repeats 23 times>

And so on… and so forth…

The great, wise ChatGPT was convinced that this was the work of the devil and that the “Microsoft Reserved Partition” partition was without a “soul” (file system) and would need to be “cast out” (excluded) by grub-prober… And then went on to instruct me to “add the file system UUID” to my /etc/default/grub via the GRUB_OS_PROBER_SKIP_LIST="<UUID>@/dev/nvme0n1p2" line… Never mind it just told me there is no file system for the MSR partition (and therefore no file system UUID)…

Continue reading

Rebuilding Ubuntu LTS on WSL2 and Interfering Docker Integrations

In an attempt to get some AMD iGPU accelerated apps to run via Ubuntu LTS on WSL2, I had rebuild my Ubuntu LTS “VM” under WSL2.

  • I had to first remove the existing Ubuntu LTS (named “UbuntuLTS”): wsl --unregister UbuntuLTS

WARNING: Although multiple sources state that the source .vhdx file does not get deleted, it actually does get deleted for me! 🙄

  • I re-downloaded the .wsl file directly from Ubuntu, then installed the VM manually:

wsl --install --from-file "ubuntu-24.04.4-wsl-amd64.wsl" --name UbuntuLTS --location "D:\WSL\UbuntuLTS" --no-launch

Note that if you have Docker already installed, the default “distro” WSL2 may have been set to Docker’s docker-desktop:

  • set the correct default: wsl --set-default UbuntuLTS
  • run wsl.exe and it will launch into the newly created distribution, set a new (default) user and password… and ignore the stupid <3>WSL (299 - Relay) ERROR: operator():579: getpwuid(1000) failed error 🙄
    • NOTE: the error will “go away” after a wsl --shutdown and restart…


  • turn on the integration in Docker again…  and watch errors pop up…
    An error occurred while running the command. DockerDesktop/Wsl/ExecError: c:\windows\system32\wsl.exe -d -e sh -c cat - > ~/.docker/config.json: exit status 1 (stderr: , wslErrorCode: DockerDesktop/Wsl/ExecError)

Continue reading

AMD Radeon Software Hanging Windows Explorer…

So, another day, another IT f*ck-up…

AMD’s in the crosshairs today. Due to having to muck around with AMD iGPUs in/on a WSL2-hosted Ubuntu LTS VM, I had to install an “older” AMD Radeon 26.2.2 driver…

Now, every time I right-clicked on a drive, a folder or a file in Windows Explorer, the stupid Radeon dashboard launches… and proceeds to “hang” Windows Explorer (with your mouse cursor turning into a spinning cursor) until something times out and hands Windows Explorer back its head…

  • No, killing the dashboard immediately does not give Windows Explorer back its head
  • No, attempting the registry hacks found across the ‘net did not help
  • No, disabling all non-Microsoft “Context Menu” items via ShellExView did not help

What did help was one of the suggestions by Google’s “AI Mode”!

i.e. F*ck Rename C:\Program Files\AMD\CNext\CNext\RadeonSoftware.exe (as an Administrator, of course).

“Unrooting” WSL…

WSL starts as root user be default.

Here’s how to ensure it runs as a “non-root user” (assumedly already created), which you then have to su and/or sudo <something> to act as root:

  • either/and:
    • modify a shortcut or change Windows Terminal’s Profile to set the distribution (if required) and the user name, and starting in the user’s home directory:
      • wsl -d <distro> -u <user> -cd ~
    • edit /etc/wsl.conf to always start with a specific user:
      • [user]
        default=<user>

Simple! (Not!)

Unifi Controller

I had a docker container of the jacobalberty/unifi “all-in-one” Unifi Network Application, and I somehow garbled the password…

The fix?

  • enter the container:
    • docker exec -it <container_name> /bin/bash
  • run MongoDB CLI:
    • mongo --port 27117
  • find the administrator user name/s:
    • use ace;
    • db.admin.find().forEach(printjson);
  • you should see one or more name entry/entries:
    • "name" : "<user_name>"
  • set/reset the password (to “password“):
    • db.admin.update( { "name" : "<user_name>" }, { $set : { "x_shadow" : "$6$ybLXKYjTNj9vv$dgGRjoXYFkw33OFZtBsp1flbCpoFQR7ac8O0FrZixHG.sw2AQmA5PuUbQC/e5.Zu.f7pGuF7qBKAfT/JRZFk8/" } } )

You should be able to log right back in with the reset password.

LAGGing pfSense… Manually…

Throughput through my KVM-hosted pfSense was abysmal for a 10Gbps link – despite the Intel Core i7 155h host w/128GB 5600Mhz RAM doing nothing else but hosting the pfSense VM (replete with VFIO-passthrough)…

I could get ~8-9Gbps iperf3 performance on from my PC to the WAN interface, which was “OK”, but iperf3 from pfSense out to various 10Gbps-capable public iperf3 servers was bad, as was Ookla speedtest.net results (from my PC).

In an attempt to figure out if the virtualisation was part of the issue, I attempted to run pfSense bare metal (via dual-booting – which had a whole storied journey itself)…

First boot brought up all the interfaces (thankfully) for selection – but no way to set up LAG then choose that for my WAN/LAN interface…

Continue reading

Upgrading WSL2 Ubuntu LTS 22.04 to LTS 24.04…

After fixing WSL networking issues, I had to upgrade the Ubuntu LTS instance… The sequence should have been:

  • apt update
  • apt upgrade -y
  • apt dist-update
  • lsb_release -a   # to confirm version before upgrade
  • do-release-upgrade
  • lsb_release -a   # to confirm version after upgrade

But, as per usual, I hit another issue attempting to upgrade (i.e. while running do-release-upgrade):

error: cannot list snaps: cannot communicate with server: Get "http://localhost/v2/snaps": dial unix /run/snapd.socket: connect: no such file or directory

A quick ‘net search brought up the point that snapd was not running…

Continue reading

Windows 11 Host Network Service (HNS) and Windows Subsystem for Linux (WSL)…

For the longest time, my Ubuntu LTS 22.04 on my (forced-to-be-updated-to) Windows 11 (replete with other networking horrors) was not working properly – I could only access the Internet from within the WSL2 container when Windows Firewall was disabled.

Despite shenanigans like attempting to whitelist a whole plethora of executables:

  • C:\Windows\System32\vmcompute.exe
  • C:\Windows\System32\vmms.exe
  • C:\Windows\System32\vmwp.exe
  • C:\Windows\System32\wsl.exe
  • C:\Program Files\WSL\wsl.exe
  • C:\Program Files\WSL\wslservice.exe

Even attempting to whitelist the usual services suspects via C:\Windows\System32\svchost.exe like the following:

  • Host Network Service
  • Internet Connection Sharing (ICS)

All were to no avail. I could resolve domain names, but no traffic went out unless the host’s Windows Firewall was disabled.

I could not even see any blocked traffic from the logs, despite having the correct set up (tip: just use WFC‘s logging interface).

Searching ChatGPT and Perplexity sent me on various wild-goose chases, from changing WSL networking modes (NAT vs. “mirrored” in %USERPROFILE%/.wslconfig), to setting up dubious firewall rules referencing InterfaceAlias using New-NetFirewallRule (but which actual interface UUIDs change every boot). Continue reading