Add CA Certificates To Python

Python checks SSL certificates when doing stuff over HTTPS. You want to make sure that the communications channel is secure. When you’re experimenting you might want to disable SSL verification (temporary), but there are scenarios where this is not possible. This happens when e.g. you need to install or update through pip, or when a library doesn’t offer a way to ignore or suppress certificate errors. This becomes a challenge in the following circumstances;

  • a company policy to check outgoing traffic by decrypting all outgoing https traffic,

  • or when you’re using tools like Burp Suite / OWASP ZAP Proxy to inspect content in API calls etc.

In these cases you’re only solution is to add the root certifcates of those MITM tools to the Python certificate bundle (or create your own bundle). In this case I’ll be adding my own Root CA certificates to the existing bundle. This is not a permanent solution, since they might get overwritten with (pip) updates. But it works for me for the time being.

Start a Python interpreter;

>>> import certifi
>>> certifi.where()
<pythonpath>\lib\site-packages\certifi\cacert.pem

This cacert.pem file contains all root CA’s typically found in most browsers and operating systems. Just add your CA (in BASE64 format) at the end of the file and you’ll be good to go (until a next certifi update).

Posted on August 22, 2023 and filed under Programming, Tips'n Tricks.

Convert Notations of Networks, Netmasks and CIDR (visa versa)

This post is basically a reminder for myself, since for some reason I run into this challenge over and over again.

The challenge is that I have to switch between the following notations:

  • 10.1.2.0/24

  • 10.1.2.0 255.255.255.0

This is because different programs/systems require different inputs, and I don’t always feel like using scripting (like Python) to transform the content.

Excel

So here are some Excel formulas that can be used.

Generate a netmask from a CIDR notation (e.g. 10.1.2.0/24) from cell A119:

=(IF(ISNUMBER(SEARCH("/32",A119)),"255.255.255.255",
IF(ISNUMBER(SEARCH("/31",A119)),"255.255.255.254",
IF(ISNUMBER(SEARCH("/30",A119)),"255.255.255.252",
IF(ISNUMBER(SEARCH("/29",A119)),"255.255.255.248",
IF(ISNUMBER(SEARCH("/28",A119)),"255.255.255.240",
IF(ISNUMBER(SEARCH("/27",A119)),"255.255.255.224",
IF(ISNUMBER(SEARCH("/26",A119)),"255.255.255.192",
IF(ISNUMBER(SEARCH("/25",A119)),"255.255.255.128",
IF(ISNUMBER(SEARCH("/24",A119)),"255.255.255.0",
IF(ISNUMBER(SEARCH("/23",A119)),"255.255.254.0",
IF(ISNUMBER(SEARCH("/22",A119)),"255.255.252.0",
IF(ISNUMBER(SEARCH("/21",A119)),"255.255.248.0",
IF(ISNUMBER(SEARCH("/20",A119)),"255.255.240.0",
IF(ISNUMBER(SEARCH("/19",A119)),"255.255.224.0",
IF(ISNUMBER(SEARCH("/18",A119)),"255.255.192.0",
IF(ISNUMBER(SEARCH("/17",A119)),"255.255.128.0",
IF(ISNUMBER(SEARCH("/16",A119)),"255.255.0.0",
IF(ISNUMBER(SEARCH("/15",A119)),"255.254.0.0",
IF(ISNUMBER(SEARCH("/14",A119)),"255.252.0.0",
IF(ISNUMBER(SEARCH("/13",A119)),"255.248.0.0",
IF(ISNUMBER(SEARCH("/12",A119)),"255.240.0.0",
IF(ISNUMBER(SEARCH("/11",A119)),"255.224.0.0",
IF(ISNUMBER(SEARCH("/10",A119)),"255.192.0.0",
IF(ISNUMBER(SEARCH("/9",A119)),"255.128.0.0",
IF(ISNUMBER(SEARCH("/8",A119)),"255.0.0.0",
IF(ISNUMBER(SEARCH("/7",A119)),"254.0.0.0",
IF(ISNUMBER(SEARCH("/6",A119)),"252.0.0.0",
IF(ISNUMBER(SEARCH("/5",A119)),"248.0.0.0",
IF(ISNUMBER(SEARCH("/4",A119)),"240.0.0.0",
IF(ISNUMBER(SEARCH("/3",A119)),"224.0.0.0",
IF(ISNUMBER(SEARCH("/2",A119)),"192.0.0.0",
IF(ISNUMBER(SEARCH("/1",A119)),"128.0.0.0",
"")))))))))))))))))))))))))))))))))

Strip the netmask bits from the CIDR notation (in cell A2):

=LEFT(A2, SEARCH("/", A2) -1)

And to convert from network address and netmask to CIDR notation (combining cell B2 with C2):

=CONCAT(B2,(
IF(C2="255.255.255.255","/32",
IF(C2="255.255.255.254","/31",
IF(C2="255.255.255.252","/30",
IF(C2="255.255.255.248","/29",
IF(C2="255.255.255.240","/28",
IF(C2="255.255.255.224","/27",
IF(C2="255.255.255.192","/26",
IF(C2="255.255.255.128","/25",
IF(C2="255.255.255.0","/24",
IF(C2="255.255.254.0","/23",
IF(C2="255.255.252.0","/22",
IF(C2="255.255.248.0","/21",
IF(C2="255.255.240.0","/20",
IF(C2="255.255.224.0","/19",
IF(C2="255.255.192.0","/18",
IF(C2="255.255.128.0","/17",
IF(C2="255.255.0.0","/16",
IF(C2="255.254.0.0","/15",
IF(C2="255.252.0.0","/14",
IF(C2="255.248.0.0","/13",
IF(C2="255.240.0.0","/12",
IF(C2="255.224.0.0","/11",
IF(C2="255.192.0.0","/10",
IF(C2="255.128.0.0","/9",
IF(C2="255.0.0.0","/8",
IF(C2="254.0.0.0","/7",
IF(C2="252.0.0.0","/6",
IF(C2="248.0.0.0","/5",
IF(C2="240.0.0.0","/4",
IF(C2="224.0.0.0","/3",
IF(C2="192.0.0.0","/2",
IF(C2="128.0.0.0","/1",
""))))))))))))))))))))))))))))))))))

The way it looks in Excel:

Some Python Code

>>> from netaddr import IPAddress
>>> print(IPAddress('255.255.255.0').netmask_bits())
24

or

>>> from ipaddress import IPv4Network
>>> print(IPv4Network('0.0.0.0/255.255.255.0').prefixlen)
24

or

>>> netmask = '255.255.255.0'
>>> print(sum(bin(int(x)).count('1') for x in netmask.split('.')))
24

or

>>> from ipaddress import IPv4Network
>>> net = IPv4Network("192.4.2.0/24")
>>> print(net.netmask)
255.255.255.0
Posted on July 28, 2023 and filed under Tips'n Tricks.

Raspberry Pi OPNsense Captive Portal Voucher Generation

When I received my new HP/Aruba iAP-305-RW access points I started to think about introducing a wireless guest network. Not a network with a pre-shared key, but something more secure and flexible. The HP/Aruba AP’s have the option for captive portal, but it doesn’t have a good integration with ACME/Let’s Encrypt certificates. My OPNsense firewall has very good integration with ACME/Let’s Encypt, and has the option of deploying a Captive Portal.

Configuring the Captive Portal on the OPNsense firewall is pretty straightforward. It’s well documented, and is up-and-running in minutes. The main challenge was creating a way to supply the credentials to the users. The default option is to generate voucher codes and print them. Not really an option, since I loose those pieces of paper before I even printed them.

The newer OPNsense software has a decent API, which also includes API options for captive portal. This opened up an option including a Raspberry Pi.

Posted on July 19, 2023 and filed under Programming, Raspberry Pi, Security, Gadgets.

Vacation Photos of Norway

This year we went to Norway for a well deserved vacation. This wasn’t our first choice, but since there was a lot of problems on Schiphol Airport, we decided that we should go by car. Since the Canary Islands are not really reachable by car the obvious choice was Norway (mainly because of the excellent infrastructure for electric vehicles).

The photos can be found on my photo website.

Below are some samples.











Posted on October 28, 2022 and filed under Holiday, Personal.

Specific Windows DNS Client routing with Powershell

Recently I ran into an issue in regards to accessing internal company websites while using the corporate VPN. Turns out that Windows has its own ideas in regards to network connections (wired/wireless) and VPN’s metrics.

The internal website was only accessible by modifying the metric on the VPN adapter to a lower than 5 value. Reason is that the metric on the ethernet adapter has a lower metric than the VPN.
Modifying the metric setting on the VPN helped, but the VPN confgi is maintained by our IT department, and they (you already guessed it) may change settings and/or reset them back to the intended defaults.

By accident I ran into a more permanent solution by invoking the powers of PowerShell. It turns out that you can manipulate the DNS Client behavior and direct DNS queries for specific hosts an/or domains to specific DNS services.

Start PowerShell with local admin rights.

Add-DnsClientNrptRule -DisplayName "My DNS Override"  -Namespace "<FQDN/domain>" -NameServers "DNSSERVER#1","DNSSERVER#2"

The minimum required number of DNS servers is 1.

This setting will survive reboots, so it’s pretty permanent.

Checking the current DNS Client settings:

Get-DnsClientNrptRule | more

Find the entry with the DisplayName giving while creating the override.
If you want to remove the entry you created you need the Name of the rule. This is represented by a GUID between curly brackets (e.g. {E5FA72F5-5575-4C15-9A2C-5F2D7B59845F}).

Remove-DnsClientNrptRule -Name "{E5FA72F5-5575-4C15-9A2C-5F2D7B59845F}"

Unfortunatelly, you cannot use the DisplayName (which is more user-friendly/readable)

Posted on August 1, 2022 and filed under Operating Systems, Tips'n Tricks.

Install a Viofo A119 Mini Dashcam in a Kia EV6

Viofo A119 Mini Dashcam

I recently decided to get a dashcam for my new Kia EV6. Previously I decided against a dashcam mainly because of the hassle of hiding the cables. I’m not a fan of seeing power/USB cables running through the car. That was until I ran into a Dongar power adapter that runs of the rearview mirror power. This means that I don’t have to bother with running cables through and behind the interior of the car.

So having found a nice alternative of routing cables I decied to do some research on which dashcam. After several hours of researching I bought the Viofo A119 Mini Dashcam. My reasons of selecting this one are;

  • WiFi support

  • 1440p (4k is nice, but you need a lot of storage)

  • Numerous parking modes incl. timelapse, motion detection (visually, and through a motion sensor)

  • Relative small

  • Decent reviews

The dashcam arrive the next day, and the Dongar adapter was still on it’s way (ordered July 8th). This meant waiting… Something I’m not really good at 😃. So I decides to give it a try without the Dongar adapter, and use the included hardwire kit (which offers recording of events when the car is powered down).

First; research in how to dismantle the interior.
I was not able to find any youtube video’s on the EV6, but I found a video on routing cables through a Kia Forte.

This video mentions a connector at the near top of the A-pillar that needs to be detached. Problem is that I wasn’t able to figure that out. Either I’m missing the right tools, of my fingers are too thick.

An image I found also describes how to detach the A-pillar cover.

After 20 minutes of frustration I was ready to give up. I had to wait for the Dongar adapter… Until I remembered that I had a nylon interior disassembly kit laying around somewhere.

Not that this helped in detaching the A-pillar covering though 🙁…

When reassembling the interior I saw that I could see the windshield through the bottom of the demi-detached covering. This was below the airbag and some connectors that are placed behind the covering. I don’t have an image of it, but the following image should give an idea on the approximate location.

Don’t feed it throw the airflow vents. When the cover is detached on the top you can see through and see the windshield.

Being able to see the windshield/front window It gave me the idea to feed the dashcam powercable through here. This went fine until the ferrite bead in the cable had to pass the plastic covering on the windshield side. Even after trying to bend the A-pillar cover with the nylon tool (second tool from the left in the image above) I wasn’t able to push the cable through.

If I can’t push it through I could try to pull it through with a piece of metal wiring. This seemed to do the trick. I fed a wire from front to back (yellow arrow), attached the power cable and pulled it through.

The red arrow is the direction the cable runs eventually, but is also the direction I had to manoeuvre to pull the cable through, since you get a bit more space the more you go higher. Don’t apply to much force, because you’re working near the airbags!

After I was able to pull the ferrite bead through, the rest was a piece of cake. It’s quite easy to push the cable behind the ceiling covering and guide ti to its final destination.

To get the cable into the fusebox, there’s a small opening between the pastic you can route the cable through.

For connecting the power cables into the fusebox I bought a set of MICRO2 adapters (available at Viofo). These hold the correct fuse size used in the Kia EV6.

Connecting these was also a challenge, since the connector is to big to correctly insert into the fusebox. Some filing was involved to remove the excess plastic on the connectors (remove some plastic on the front and back of the connector).

This results in the following fusebox view;

The final result:

Posted on August 1, 2022 and filed under Gadgets, Tips'n Tricks, Hardware.

Fortiswitch And SFP's

Last month, I started to update my lab network. The old Juniper EX ‘core’ switch was replaced by a FortiSwitch 108E-POE. The problem was that the Juniper had 14 * 1Gbps interface, and the FortiSwitch only 8, with an additional 2 * SFP Gb ports.

A couple of well known venders ship hardware that won’t allow offbrand (cheaper) SFP’s, but the FortiSwitch has no issues with a mix of vendors. Currently it hold an (ancient) Tippingpoint 1Gbps SFP (RJ45) and a new Ubiquity 1Gbps SPF (RJ45).

fortiswitch # get switch modules detail ____________________________________________________________ Port(port9) identifier SFP/SFP+ connector Unk(0x00) transceiver 1000-Base-T encoding 8B/10B Length Decode Common length_smf_1km N/A length_cable 100 meter SFP Specific length_smf_100m N/A length_50um_om2 N/A length_62um_om1 N/A length_50um_om3 N/A vendor UBNT vendor_oid 0x000000 vendor_pn UF-RJ45-1G vendor_rev vendor_sn X20092805573 manuf_date 08/18/2020 ____________________________________________________________ Port(port10) identifier SFP/SFP+ connector Unk(0x00) transceiver 1000-Base-T encoding 8B/10B Length Decode Common length_smf_1km N/A length_cable 100 meter SFP Specific length_smf_100m N/A length_50um_om2 N/A length_62um_om1 N/A length_50um_om3 N/A vendor AVAGO vendor_oid 0x00176A vendor_pn ABCU-5700RZ-TP1 vendor_rev vendor_sn AN1006ANNX manuf_date 02/13/2010

I wouldn’t advise this in any production environment, but for a home/dev environment it works (so far) and it’s (much) cheaper. The Ubiquiti SFP was around €25 (retail) here in the Netherlands, which is about a fifth of the official Fortinet SFP price.

Posted on October 25, 2021 and filed under Hardware, Tips'n Tricks.

Clear Cookies in Postman

During a Proof-of-Concept I ran into some challenges while using Postman. I had to test certain API calls based on different user-credentials, and for some reason eveything kept working like I was the super-admin.

Turned out that the application used cookies, and after the initial authentication of the super-admin, postman used to cookie to authenticate the new sessions based on another username and password.

Thankfully, it’s possible to delete cookies in postman before running a request in the ‘Pre-request Script’.

Just add the following script in the ‘Pre-request Script’ section of the request, or Collection;

const jar = pm.cookies.jar(); jar.clear(pm.request.url, function (error) { // error - <Error> });
2021-10-08.png

There’s one other setting that needs to be set, and that’s in the cookies section where you need to Whitelist the domain. Which allows Postman to interact with cookies from that domain.

2021-10-08_10-32-42.png
2021-10-08_10-33-16.png

Add the domain (or in my case the IP address) show that issued the cookie to the whitelist domains

2021-10-08_10-33-28.png

After that, the cookies can automatically be removed by the ‘Pre-request Script’, and everything would work as I intended.

Posted on October 8, 2021 and filed under Programming, Tips'n Tricks.

Replace Intel NUC8 Fan (model: BSC0805HA-00)

About 2 years ago I bought an Intel NUC 8 to be used as a Linux server at home. Since it runs 24/7/365, it’s just a matter of time when the fan will fail. That time was about 5-6 weeks ago.

NUC8 Fan Model BSC0805HA-00

NUC8 Fan Model BSC0805HA-00

The internal fan (model: BSC0805HA-00) of the NUC 8 is not your average computer fan, and it’s also different from the earlier and later NUC versions. The fan for the older and newer NUC versions are abundantly available online through the regular channels. Not so much luck for the NUC 8 model…

There are some vendors on AliExpress that sell this type of fan. The problem is that I normally buy stuff from vendors that have sold hundreds of the item I want or need (there’s a difference :-) ).

Since there was no Dutch or European shop that had these fans in stock I had to try. It was that or buy a new NUC ($$$).

The fan I bought on AliExpress was ~$25USD, which was basically the cheapest option available. It arrived after about 3 weeks and it looked like the real thing.

On the left the new AliExpress fan. On the right the old noisy fan still attached to the NUC

On the left the new AliExpress fan. On the right the old noisy fan still attached to the NUC

After replacing the fan it was dead-quiet again in my room (and yes, the fan still moved air through the NUC). Now fingers crossed that this fan holds out for another 2 years.

B.t.w. If you’re looking for instructions on how to disassemble the NUC; just try YouTube

UPDATE @ 08-20-2022: The fan actually lasted a little bit more than a year. I ordered a new fan (from a local NUC ports supplier) yesterday. Let’s see how long that fan will last.

Posted on July 29, 2021 and filed under Hardware.