Posts filed under Tips'n Tricks

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.

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.

My First Docker Deployment

About two weeks ago I had to get a crash-course in Docker technology at work. I had no idea what I was doing (following a YouTube video and an accompanying PDF. Eventually I got it to work but no idea what I was doing. So I wanted to change that.

NOTE: I’m not gonna build/create new docker containers yet. Just learning on how they are used, configured, and interact. This is also no tutorial on how to install Docker itself. There are more than enough websites for that.

The problem with learning new things is that they have to be practically and/or useful (for me). After some thought I ended up with a combination of Transmission and OpenVPN.

This Docker image gives you a Torrent client with a webgui, and all (torrent) traffic is directed through the OpenVPN connection. Making it safe to download Linux distro’s. As a bonus, it has a generic web proxy function with you can use to handle your web traffic. The latter is especially useful in combination with e.g. the browser extension/plugin FoxyProxy.

Deploying the docker container is pretty straight-forward (you do need a supported VPN provider). It basically works out of the box, but molding it to my wishes involved a bit more digging around. There are some things I wanted to add, or change;

  • Customer paths for the download locations (default = /data).

  • Use a watchfolder for transmission where the .torrent files can be picked-up.

  • Use an additional reverse proxy for the Transmission webGui so that all my internal services are accessible from 1 IP address without having to remember al their TCP ports.
    More info on that can be found here.

  • Since the Docker container runs under a/the root account, I needed to change that behavior since I don’t want to do everything with root permissions (involving experimentation with umask and UID/GID’s).

This resulted in the following docker-compose file (docker-compose.yaml):

UPDATE: I’ve added the Portainer image to the compose file. This gives you a web gui to manage the containers. The gui is accessible on port 9000 on the same docker host.

version: '2'
services:
    transmission-openvpn:
        restart: unless-stopped
        volumes:
            - '/mnt/data:/data'
            - '/mnt/stack/Watchfolder:/home/Watchfolder'
            - '/etc/localtime:/etc/localtime:ro'
        environment:
            - TZ=Europe/Amsterdam
            - OPENVPN_OPTS=--inactive 3600 --ping 10 --ping-exit 60
            - CREATE_TUN_DEVICE=true
            - OPENVPN_PROVIDER=NORDVPN 
            - OPENVPN_USERNAME=<VPN-USERNAME>
            - OPENVPN_PASSWORD=<VPN-PASSWORD>
            - NORDVPN_COUNTRY=CH
            - HEALTH_CHECK_HOST=google.com
            - TRANSMISSION_INCOMPLETE_DIR_ENABLED=true
            - TRANSMISSION_INCOMPLETE_DIR=/data/downloads/incomplete
            - TRANSMISSION_DOWNLOAD_DIR_ENABLED=true
            - TRANSMISSION_DOWNLOAD_DIR=/data/downloads/complete
            - TRANSMISSION_WATCH_DIR_ENABLED=true
            - TRANSMISSION_WATCH_DIR=/home/Watchfolder
            - TRANSMISSION_TRASH_ORIGINAL_TORRENT_FILES=true
#            - TRANSMISSION_UMASK=222
            - TRANSMISSION_SPEED_LIMIT_DOWN=5000
            - TRANSMISSION_SPEED_LIMIT_DOWN_ENABLED=true
            - TRANSMISSION_SPEED_LIMIT_UP=1000
            - TRANSMISSION_SPEED_LIMIT_UP_ENABLED=true
            - WEBPROXY_ENABLED=true
            - WEBPROXY_PORT=8080
            - LOCAL_NETWORK=192.168.0.0/16
            - PUID=1000
            - PGID=1000
        cap_add:
            - NET_ADMIN
        logging:
            driver: json-file
            options:
                max-size: 10m
        ports:
                - '9091:9091'
                - '8888:8080'
        image: haugene/transmission-openvpn
        container_name: openvpn
    portainer:
        image: portainer/portainer-ce
        container_name: portainer
        restart: always
        ports:
          - "9000:9000"
        command: -H unix:///var/run/docker.sock
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock
          - portainer_data:/data

volumes:
  portainer_data:

The thing that took the most amount of time to figure out was the PUID/PGID part of the config. This basically are the user id and group id which are used to run the container and also when creating directories and files on the physical filesystem of the host. In my case, the PUID, and PGID are the id’s corresponding to my username on the Linux host.

The important part is that all the path references in the environment part of the yaml file are local to the container. These are mapped/related to the physical locations in the volumes part of the config file.

Deploying/creating the Docker container is done through the following command (I use docker-compose instead of docker run):

docker-compose up -d

Configuring a webproxy in my browser pointing to the Linux host IP with port 8888 allows me to surf the web through the OpenVPN provider. Pointing my browser to the Linux host IP address with port 9091 gives the Transmission webGui (http://IP-ADDRESS>:9091). But as I mentioned earlier, I want to access this through my internal reverse proxy (NGINX).

To do this I have to create an additional location within the NGINX config and enable that. This resulted in the following NGINX location config file:

location /transmission/ {
      proxy_pass http://192.168.##.1:9091;

      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-NginX-Proxy true;
      proxy_http_version 1.1;
      proxy_set_header Connection "";
      proxy_pass_header X-Transmission-Session-Id;
      add_header   Front-End-Https   on;

      satisfy any;
      allow 192.168.0.0/16;
      allow 172.16.16.0/24;
      allow 10.200.200.200/32;
      deny all;
      auth_basic "Restricted Content";
      auth_basic_user_file /etc/nginx/auth.d/auth.pwd;
}

Note that the bottom part are some directoves to limit the IP’s that can access the page. These are related to your internal IP networks.

Now I can access the tranmission webGui over https through my NGINX reverse proxy via https://internalhost/transmission

A small note on the use of FoxyProxy; This extension allows you to selectively use the proxy based on (parts of ) URL. You can configure patterns using wildcards and regular expressions to direct traffic directly or through a proxy.

So if e.g. your OpenVPN terminates in the the US, you can create a pattern that certain entertainment sites are being accessed through your proxy, while other traffic uses your regular ISP. This is especially useful if you have a capped monthly VPN account.

Posted on July 29, 2020 and filed under Linux, Programming, Security, Software, Tips'n Tricks.

Keepass Password Generator

With the increasing password complexity demands in both online and offline services, you basically can’t live without a password manager. Personally I use 1Password, but at work Keepass is recommended. Main reason is that it remains local (no passwords in the cloud). Downside is that you need to have a proper backup in case of emergencies (or rely on decent password reset mechanisms.

Since a generic password scheme is obvious highly overrated, you basicalle need a different password scheme for every website, application or service. The worst being password schemes that limit the amount of characters to between 6 and 10…. Seriously? Others limit the amount of special characters like @\/’”| because of some fear of SQL injection schemes. Which is not a problem if you implement the backend correctly…. But that’s for another day.

Due to all these password challenges I had to reconfigure my Keepass (default) password generator to be a bit more friendly. For those bad password scheme website I have specific generation algoritms, and in a few cases the demands on the password are so ridiculous that I had to make a generator just for that service.

Anyway, the latest ‘challenge’ was that a service demanded a letter at the start and finish of the password, so that resulted in the following pattern:

L[uullddss]{22}L

keepass_pswd_gen_01.png

This results in a password:

  • Starting with a mixed-case letter (L), followed by a 22 character mix of at least

  • 2 upper-case (uu) letters (ABCDEFGHIJKLMNOPQRSTUVWXYZ),

  • 2 lower-case (ll) letters (abcdefghijklmnopqrstuvwxyz),

  • 2 digits (dd) (1234567890),

  • 2 printable special characters (ss) ( !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ ),

  • and finishing with another mixed case letter (ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)

Note that the previous default password length was 22 character, so increasing it with 2 additional letters to 24, the password became a bit stronger. Otherwise the password would have weakened substantially, because the first and last character was one out of 52.

This results in the following preview:

When you need to communicate passwords, or manual type them (on another device) it might be helpful to exclude certain characters that (depending on the font) look alike (e.g. 1Il|, O0). This can be accomplished in the ‘Advanced’ tab of the password generator.

Note that excluding these characters reduce the complexity of the password (which can be corrected up to some extend by increasing the password length).

And in those weird cases where certain character are not allowed you can use the ‘exclude characters’ option in the screenshot above (make sure you increase the password length accordingly to maintain password security).

Posted on June 8, 2020 and filed under Security, Tips'n Tricks.

Xiaomi Xiaofang Wireless Camera Custom Firmware Hack

A colleague of mine demonstrated a Wyze webcam a couple of weeks before. A nifty little FullHD wireless IP camera that has a decent (iOS/Android) app and cloud connectivity to store the data.
I liked everything about it, except the cloud-storage part. I don’t like it when I don’t know where my private data resides. So I started a to search to see if these devices could be altered to benefit my needs, and guess what, they can be altered.

There’s a github project where they fabricated a firmware hack and with custom software the camera can be used for much more. So now I had to get my hands on the most inexpensive version of the camera. Since there are different brands that ship basically the same hardware with a different firmware, there’s more than enough choice.

Posted on November 19, 2019 and filed under Gadgets, Hardware, Security, Review, Tips'n Tricks.