Web Echo Service for developers

I recently had need of a service that would return your query web to you for web client (or proxy) development purposes, in a case where using Fiddler, Wireshark, tcpdump et.al. was proving difficult for various reasons. The solution became the C-Net Echo Service, available at https://echo.c-net.org/ (and over plain HTTP if you need it). Feel free to use this for whatever.

Example usage:

$ curl -X PUT -d "Hello World!" -H "User-Agent: Fake Agent" -H "CUSTOM-HEADER: foo" -H "X-Forwarded-For:" "https://echo.c-net.org/"
PUT / HTTP/1.1
Host: echo.c-net.org
Accept: */*
User-Agent: Fake Agent
Content-Type: application/x-www-form-urlencoded
Connection: Keep-Alive
Content-Length: 12

Hello World!

Generating a C# library from swagger.json using Docker for Windows

Just a short reference for myself (and maybe for you). How to run Docker for Windows, mount a local file system drive inside of the container, grab the swagger.json file off of a URL, and generate a library:

Using swagger-codegen-cli (old):

docker run -it -v //c/temp/swagger:/local --network host --rm swaggerapi/swagger-codegen-cli generate -i "http://docker.for.win.localhost:5000/swagger/v1/swagger.json" -l csharp -o /local

Using openapi-generator-cli (new):

docker run -it -v //c/temp/swagger:/local --network host --rm openapitools/openapi-generator-cli generate -i "http://docker.for.win.localhost:5000/swagger/v1/swagger.json" -g csharp -o /local

In the examples, the generators connect to a webserver running on the local Windows host at port 5000, and outputs “csharp”. Change this as appropriate.

Oh, and another thing: To make NSwag generate the swagger.json correctly in a .Net project, the <GenerateDocumentationFile> property needs to be set.


Remote Desktop (RDP) to a computer that’s enrolled in Azure AD

If you attempt to connect to a machine that’s enrolled in Azure AD from a workstation that’s not part of the domain, like your desktop or laptop at home, you’ve likely encountered this issue.

Firstly, we should get a few basics out of the way. You need a correct username and password. When your user is in AzureAD, you need to specify your username as such:

You also need to log into the target machine and allow remotely showing the login screen through RDP, which means disabling the requirement to use Network Level Authentication. This will allow you to log in interactively:

Note that the checkbox must be deselected for interactive login sessions to work.

Now we need to go about modifying our .rdp files. You can get a .rdp file by pressing “Save As” in the Remote Desktop Connection window. Open the file with Notepad (or your favorite editor), and you’ll get lines such as these:

At the end of the file, we need to enable support for CredSSP if you want to connect to an AzureAD enrolled machine. Add a line like this:


You can also put your username in the file, with the domain, as such:


You can also put your password in the file, though I don’t recommend the latter. This is likely to be a company computer, after all. Check your IT policies and proceed at your own risk.

Here be monsters.

Passwords in the .rdp file can be encrypted as SecureStrings. You can generate them with PowerShell. Keep in mind that SecureStrings are encrypted using your current account, so you have to do this while logged in on the machine on which you want to use the .rdp file. The client, not the remote machine.

> "Hunter2" | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString

All of that garble is your encrypted password (Hunter2). Your password is now also stored in your PowerShell. Not good. If you do this without specifying the password, it’ll ask you. Better. Slightly.

ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString

You can put the password (if you really want to) into your .rdp file as such:

password 51:b:01000000d08c9ddf0115d1118c7a00c04fc297eb010000000f16d2079232d84babe49f4bac6617ef0000000002000000000003660000c000000010000000e686a1ac13248c81a2c9abb56082452f0000000004800000a0000000100000002a071ce0035f888093d04bdc4d8716aa100000005590842a9ba86481072a0e444971e7e014000000871ea7bed2d1abdc67222644e9a4c98addb76b7b

Note: The syntax is “password 51:b:encryptedpasswordhere“. There’s a space, not a newline. Don’t trust your browser.

Happy remote working!

curl SSL fails even with ca-certificates installed

curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

So curl fails to access sites over https, even if ca-certificates is installed in your Docker container? You need to force a certificate rehash. Why this is not done by default escapes me.


curl should be happy now. Enjoy!

Perl one-liner to create random passwords

Just wrote this thing. Putting it here, in case anyone needs it.

perl -e 'my @c = (('a'..'z'), ('A'..'Z'), (0..9)); for(1..128) {print $c[int(rand($#c+1))]}'

It creates random passwords, with the length specified by the number following “1..”, which is 128, in this example.

Example outputs:




Disable the “Other people are logged on to this computer” message on a Windows VM

If you’re logged on with Remote Desktop (and probably in several other cases) Windows will not respond appropriately to the power button being pressed. Instead of shutting down, it will display a message asking you if that’s what you really want to do, as if holding the same button for 5 seconds to force the damn thing to shut down isn’t your next move.

This solution may or may not be Windows XP specific, as that’s where I encountered the issue, but I’ve confirmed that setting the following registry key removes this message and shuts down when a simulated ACPI button is pressed:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Error Message Instrument]

How to use Invoke-WebRequest in PowerShell without having to first open Internet Explorer

So, you get this error message:

Invoke-WebRequest : The response content cannot be parsed because the Internet Explorer engine is not available, or Internet Explorer’s first-launch configuration is not complete. Specify the UseBasicParsing parameter and try again.

..and sure, you could use -UseBasicParsing but, depending on your use case, you might then have to write a lot of functionality yourself that’s already handled for you if you avoid basic parsing.

Luckily, the Internet Exporer First Run wizard can be disabled in the registry, and if your script runs as a privileged user, you can do this from PowerShell:

$keyPath = 'Registry::HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Internet Explorer\Main'
if (!(Test-Path $keyPath)) { New-Item $keyPath -Force | Out-Null }
Set-ItemProperty -Path $keyPath -Name "DisableFirstRunCustomize" -Value 1


It’s worth noting that if your computers are in a domain, there’s also an easy to use GPO for this, at Computer Configuration => Policies => Administrative Templates => Windows Components => Internet Explorer, called Prevent running First Run wizard.

More about that over here (local archive).

“Invalid provider type specified” CryptographicException when accessing the PrivateKey property of a certificate in C#/.Net

We recently encountered this in a production environment: A customer had installed a new certificate, and this exception began showing up in the logs. Luckily, the application was smart enough to at least fall back on using the previous (not yet expired) certificate, so no downtime occurred.

Turns out the customer had been provided with a certificate with the private key in CNG format. This is not compatible with several versions of .Net. The solution was to convert the key to a standard RSA key using the following commands on a machine with OpenSSL installed:

# You need to set these to match your environment
cert="CertificateFileNameHere.pfx" password="TopSecretCertificatePasswordHere"
# These should run as is - they use the variables provided above openssl pkcs12 -in "${cert}.pfx" -nokeys -out "${cert}.cer" -passin "pass:${password}" openssl pkcs12 -in "${cert}.pfx" -nocerts -out "${cert}.pem" -passin "pass:${password}" -passout "pass:${password}" openssl rsa -inform PEM -in "${cert}.pem" -out "${cert}.rsa" -passin "pass:${password}" -passout "pass:${password}" openssl pkcs12 -export -in "${cert}.cer" -inkey "${cert}.rsa" -out "converted.pfx" -passin "pass:${password}" -passout "pass:${password}"

Importing the converted certificate back into Windows’ Certificate Store, the .Net application was capable of loading it just fine.

The solution was mostly found here.

Docker starts slowly on Raspberry Pi / Raspbian

After installing the latest stable version of docker-ce (5:18.09.0~3-0~raspbian-stretch as of the time of writing), Docker would take ages to start after a reboot. Commands would even time out waiting for it.

/var/log/daemon.log shows a gap of almost 4 minutes between the attempt to start the Docker Application Container Engine and the first log line from dockerd.

Jul  5 10:10:37 RPi systemd[1]: Starting Docker Application Container Engine...
Jul 5 10:14:07 RPi dockerd[683]: time="2019-07-05T10:14:07.808215720+02:00" level=info msg="parsed scheme: \"unix\"" module=grpc

After installing a later version of docker-ce from the test branch in attempt to remedy this, I got an interesting message while the issue persisted:

Jul  5 10:42:18 RPi systemd[1]: Starting Docker Application Container Engine...
Jul 5 10:43:30 RPi dockerd[720]: crypto/rand: blocked for 60 seconds waiting to read random data from the kernel
Jul 5 10:47:27 RPi dockerd[720]: time="2019-07-05T10:47:27.245479521+02:00" level=info msg="Starting up"

Turns out it doesn’t have enough random entropy to start. We can help the Pi generate this by running haveged. A quick apt-get install haveged and a reboot later, the logs look much better, and Docker starts immediately.

# apt-get install haveged
# reboot

The result, after downgrading to the stable version of Docker again:

Jul  5 11:08:02 RPi systemd[1]: Starting Docker Application Container Engine...
Jul 5 11:08:06 RPi dockerd[707]: time="2019-07-05T11:08:06.793516408+02:00" level=info msg="parsed scheme: \"unix\"" module=grpc

From 4 minutes to 4 seconds is a rather significant improvement, I think 🙂