Squoggle

Mac's tech blog

The TLS 1.2 Handshake Explained: Securing Your Online Data with a Twist

Introduction

Howdy, folks! In today’s digital age, the need for secure online communication is more important than ever. And that’s where the Transport Layer Security (TLS) protocol comes in. It’s the trusty sidekick that keeps your sensitive data safe from prying eyes. In this blog post, we’re going to take a down-home look at the TLS 1.2 handshake process to help you understand how it ensures secure communication between your computer and the websites you visit.

1. The Meet and Greet

When you decide to visit a secure website, your computer (the client) and the website’s server start a friendly little dance called the TLS handshake. The first step of this dance is the “Client Hello” message, where your computer sends a list of its preferred cryptographic algorithms and a random number to the server. It’s sort of like saying, “Howdy, partner! These are the steps I know. What about you?”

2. The Server’s Response

Next, the server picks the best matching cryptographic algorithms and sends a “Server Hello” message back to the client, sharing its own random number. In addition, the server sends its digital certificate, which is like a digital ID card, to prove its identity. It’s the server’s way of saying, “Well, howdy! I reckon we can dance to the same tune. Here’s my ID, just so you know I’m legit.”

3. Checking Credentials

Your computer takes a gander at the server’s certificate and verifies it with the certificate authority (CA) that issued it. If everything checks out, your computer says, “Well, alrighty then! You seem like a fine partner for this dance.”

4. The Secret Handshake

Now that both sides have agreed on the steps, it’s time to create a secret key for encrypting and decrypting the data. Your computer generates a “pre-master secret” and encrypts it with the server’s public key from its certificate. This encrypted pre-master secret is then sent back to the server, which decrypts it with its private key. It’s like sharing a secret handshake that only the two of them will know.

5. Securing the Dance Floor

With the pre-master secret securely exchanged, both your computer and the server derive the same “master secret.” From this master secret, they generate symmetric encryption keys and other required cryptographic material. It’s like setting up a private dance floor, so no one can see or interfere with your moves.

6. The Final Steps

Finally, both the client and the server send “Change Cipher Spec” and “Finished” messages to each other, indicating that they’re ready to start using the newly established encryption keys. It’s like saying, “Alright, partner, let’s start dancing with our new secret steps!”

Conclusion

And there you have it, folks! That’s the TLS 1.2 handshake in a nutshell. This trusty process keeps your online chats safe and sound, ensuring that your sensitive data is encrypted and secure from eavesdroppers. So the next time you visit a secure website or send a confidential email, remember to tip your hat to the hardworking TLS 1.2 handshake that keeps your information safe as houses.

CentOS Drive Testing

My Server was making noises that were uncharacteristic. This is how I tested my hard drives for failure.

  1. Install smartmontools:
    # yum install smartmontools
  2. Get a listing of all your hard drives:
    # lsblk
  3. Run a test on one of the hard drives:
    # smartctl -t short /dev/sda
    You will see something similar to the following:
    smartctl 7.0 2018-12-30 r4883 [x86_64-linux-3.10.0-693.11.6.el7.x86_64] (local build)
    Copyright (C) 2002-18, Bruce Allen, Christian Franke, www.smartmontools.org
    === START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===
    Sending command: "Execute SMART Short self-test routine immediately in off-line mode".
    Drive command "Execute SMART Short self-test routine immediately in off-line mode" successful.
    Testing has begun.
    Please wait 2 minutes for test to complete.
    Test will complete after Fri Sep 23 13:02:21 2022
    Use smartctl -X to abort test.
  4. It will give you a time when you can check the results. When the time has elapsed, come back and check the results like this:
    # smartctl -H /dev/sda
    smartctl 7.0 2018-12-30 r4883 [x86_64-linux-3.10.0-693.11.6.el7.x86_64] (local build)
    Copyright (C) 2002-18, Bruce Allen, Christian Franke, www.smartmontools.org
    === START OF READ SMART DATA SECTION ===
    SMART overall-health self-assessment test result: PASSED
  5. If the test fails you will see something like this:
    # smartctl -H /dev/sdb
    smartctl 7.0 2018-12-30 r4883 [x86_64-linux-3.10.0-693.11.6.el7.x86_64] (local build)
    Copyright (C) 2002-18, Bruce Allen, Christian Franke, www.smartmontools.org
    === START OF READ SMART DATA SECTION ===
    SMART overall-health self-assessment test result: FAILED!
    Drive failure expected in less than 24 hours. SAVE ALL DATA.
    Failed Attributes:
    ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
    5 Reallocated_Sector_Ct 0x0033 063 063 140 Pre-fail Always FAILING_NOW 1089
  6. Looks like you need to replace /dev/sdb

How to Replace the Hard drive

This is what I did to replace the hard drive.

  1. Install lshw package:
    # yum install lshw
  2. Now list hardware of type disk:
    # lshw -class disk
    You should get way to much info.
  3. Filter the info with grep like so:
    # lshw -class disk | grep -A 5 -B 6 /dev/sdb
    You should now only get the one drive you are looking for.
    Mine looks like this:
    # lshw -class disk | grep -A 5 -B 6 /dev/sdb
    *-disk:1
    description: ATA Disk
    product: WDC WD1002FAEX-0
    vendor: Western Digital
    physical id: 1
    bus info: scsi@5:0.0.0
    logical name: /dev/sdb
    version: 1D05
    serial: WD-WCATR1933480
    size: 931GiB (1TB)
    capabilities: partitioned partitioned:dos
    configuration: ansiversion=5 logicalsectorsize=512 sectorsize=512 signature=000cd438

So it looks like I need to replace a 1TB Western Digital. Fortunately this disk is in a two disk raid array.

Remove the HD from the Raid Array

This is what I did to remove the HD from the Raid Array. Before proceeding back up everything. I do a daily offsite backup so am covered in theory.

  1. Redo the lsblk command from above to confirm which disk is which:
    # lsblk
    NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
    sdb 8:16 0 931.5G 0 disk
    └─sdb1 8:17 0 931.5G 0 part
    └─md0 9:0 0 931.4G 0 raid1
    └─vg_raid-lv_raid 253:4 0 931.4G 0 lvm /mnt/Raid
    sdc 8:32 0 931.5G 0 disk
    └─sdc1 8:33 0 931.5G 0 part
    └─md0 9:0 0 931.4G 0 raid1
    └─vg_raid-lv_raid 253:4 0 931.4G 0 lvm /mnt/Raid
  2. Remember that the defective disk in this case is /dev/sdb and the good one is /dev/sdc
  3. Write all cache to disk:
    # sync
  4. Set the disk as failed with mdadm:
    # mdadm --manage /dev/md0 --fail /dev/sdb1
    This is the failed partition from /dev/sdb.
    You should see something like this:
    mdadm: set /dev/sdb1 faulty in /dev/md0
  5. Confirm it has been marked as failed:
    # cat /proc/mdstat
    Personalities : [raid1]
    md0 : active raid1 sdc1[1] sdb1[0](F)
    976630464 blocks super 1.2 [2/1] [_U]
    bitmap: 0/8 pages [0KB], 65536KB chunk

    The (F) next to sdb1 indicates Failed.
  6. Now remove the disk with mdadm:
    # mdadm --manage /dev/md0 --remove /dev/sdb1
  7. Now confirm with the cat command as before:
    # cat /proc/mdstat
    Personalities : [raid1]
    md0 : active raid1 sdc1[1]
    976630464 blocks super 1.2 [2/1] [_U]
    bitmap: 0/8 pages [0KB], 65536KB chunk

    Notice that sdb1 is now gone.
  8. You can also confirm this with the lsblk command:
    # lsblk
    NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
    sdb 8:16 0 931.5G 0 disk
    └─sdb1 8:17 0 931.5G 0 part
    sdc 8:32 0 931.5G 0 disk
    └─sdc1 8:33 0 931.5G 0 part
    └─md0 9:0 0 931.4G 0 raid1
    └─vg_raid-lv_raid 253:4 0 931.4G 0 lvm /mnt/Raid
  9. You can now shutdown the server and replace that hard drive.
    It is easy to find the correct hard drive with the serial number you got from the lshw command you ran earlier. The serial number is: WD-WCATR1933480
  10. Power on server.
  11. Here is where I ran into an issue that left me scratching my head for quite some time. I’m documenting it here so if it happens again I can resolve it quickly.
    It turns out that the spare drive I had on hand I thought was new but was not. It was actually a drive I had installed in another system that was retired and this drive had a boot partition on it. When I booted the server, that was the partition that booted instead of my regular boot partition. I even had to recover passwords on it because the user and root passwords were not the same. All along I was thinking something had happened to bork the users somehow. But it turns out the new drive I had put in was booting and it was not really new. Lesson learned here is to make sure the drive you put in has had any partitions removed. I did this by putting the drive in another system and using fdisk to remove the partitions. Now when I boot the server the normal boot partition boots and this new drive is designated as sdb as I expect.
  12. Now you can copy the partition information from the good disk (/dev/sdc) to the new disk (/dev/sdb). Be warned that this will destroy any partition information on the new disk. Since I already destroyed any partition information in the previous step I’m good with this. The command looks like this:
    # sfdisk -d /dev/sdc | sfdisk /dev/sdb
  13. You can check the partition info is correct with the lsblk command:
    # lsblk
    NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
    sdb 8:16 0 931.5G 0 disk
    └─sdb1 8:17 0 931.5G 0 part
    sdc 8:32 0 931.5G 0 disk
    └─sdc1 8:33 0 931.5G 0 part
    └─md0 9:0 0 931.4G 0 raid1
    └─vg_raid-lv_raid 253:2 0 931.4G 0 lvm /mnt/Raid
  14. Now you can reverse the process and create the mirror that you previously had like this:
    # mdadm --manage /dev/md0 --add /dev/sdb1
  15. Now you can verify the status of your raid like this:
    # mdadm --detail /dev/md0
# mdadm --detail /dev/md0
/dev/md0:
           Version : 1.2
     Creation Time : Tue Jun 27 17:49:31 2017
        Raid Level : raid1
        Array Size : 976630464 (931.39 GiB 1000.07 GB)
     Used Dev Size : 976630464 (931.39 GiB 1000.07 GB)
      Raid Devices : 2
     Total Devices : 2
       Persistence : Superblock is persistent

     Intent Bitmap : Internal

       Update Time : Sat Sep 24 14:46:35 2022
             State : clean, degraded, recovering 
    Active Devices : 1
   Working Devices : 2
    Failed Devices : 0
     Spare Devices : 1

Consistency Policy : bitmap

    Rebuild Status : 1% complete

          Name : Serenity.localdomain:0  (local to host Serenity.localdomain)
          UUID : f06aeaae:e0c9707b:6d982f07:3f320578
        Events : 114297

Number   Major   Minor   RaidDevice State
   2       8       17        0      spare rebuilding   /dev/sdb1
   1       8       33        1      active sync   /dev/sdc1
  • You can see that the ‘Rebuild Status is at 1% and that this is in a rebuilding state.
  • You can get the status of the rebuild like so:
    # cat /proc/mdstat
# cat /proc/mdstat
Personalities : [raid1] 
md0 : active raid1 sdb1[2] sdc1[1]
      976630464 blocks super 1.2 [2/1] [_U]
      [>....................]  recovery =  0.7% (7077312/976630464) finish=129.7min speed=124486K/sec
      bitmap: 8/8 pages [32KB], 65536KB chunk

You can watch this command if it is interesting to you.

There’s something missing here. It probably relates to this:

CentOS 7 created mdadm array disappears after reboot

My Python Notes

Virtual Environments for Python

Python3 is already installed on my Linux distro.

Install Virtual Environments

You will want to use Virtual Environments for Python. Install Virtualenv:

$ pip install virtualenv

Create a Virtual Environment

Create a base directory where you want your Virtual Environments to live:

$ cd ~
$ mkdir -p Python/VirtualEnv

Now create a Virtual Environment within that directory structure. I’m going to use P3VirtEnv to signify it is a Python 3 Virtual Environment.

$ cd ~/Python/VirtualEnv
$ virtualenv P3VirtEnv

You should see some message that essentially mean that the Virtual Environment was successfully created. You should see a new directory named ~/Python/VirtualEnv/P3VirtEnv.

Now you need to enter the Virtual Environment and set it active:

$ cd P3VirtEnv/
$ source bin/activate

Your prompt will now show what environment you are logged into. At this point it looks like this:

(P3VirtEnv) mac@Gob:~/Python/VirtualEnv/P3VirtEnv$

This process essentially copies your Python installation form the standard location to this Virtual Environment.
You can test this by seeing where Python is installed

$ which python
/home/mac/Python/VirtualEnv/P3VirtEnv/bin/python

Exit the Virtual Environment by simply typing the word deactivate.

$ deactivate

Your prompt and path are now returned to normal.

sdfsdfsdf

Packages

Python has packages that can be installed.

To see what packages have been installed do:

$ pip list

You should see a list of all the packages that have been installed. Mine looks something like this at this point:

Package Version
---------- -------
pip        22.2.2
setuptools 65.3.0
wheel      0.37.1

To see a list of all packages that have been installed by pip then do:

$ pip freeze

Why the virtualenv package is not listed is a mystery to me at this point.

Now is a good time to check that out. Install Selenium like this:

$ pip install selenium

A whole bunch of stuff gets installed. Now you can check pip freeze again and see all of what got installed

Another library that we will need for making API calls is called Requests. Install it like this:

$ pip install requests

The do the freeze thing to verify.

Install PyCharm

Instructions for downloading and installing PyCharm are located here:

https://www.jetbrains.com/help/pycharm/installation-guide.html

Review Section 2, Chapter 10 in the Class

Variables

When you define a string as a variable you can use a single quote or double quote to encapsulate the string. Numbers do not need to be put in quotes. I think if you put it in quotes then it becomes a string and not a number.

Variables cannot start with a Number, just letters or Underscore. The variable may contain numbers or underscore but cannot start with a number.

Data Types

Integers

Integers are numbers without decimals. They can be positive, negative or zero.

You can do math on integers such as Addition, subtraction, multiplication and division as well as other operations.

If you have multiple operations in a single line you should use parenthesis.

Float

Floats (Floating Point Numbers) are numbers with decimal places.

Operations on floating numbers will result in floating numbers.

In Python if you were comparing 1 vs 1.0 the comparison would be false because the first is an integer and the second is a float.

Strings

Strings are a sequence of single characters and are represented with quotes. Quotes can be single or double.

You can use one type of quote within the other type but not one type within the same type.

For example these is valid:

"Bring me your 'stash' of contraband"

But this is not valid:

"Bring me your "stash" of contraband"
Slicing

Slicing or a Slice is a subset of a String. The index number is the character counting from either right or left of the string and gives you a specific character of the string. See chapter 16 in the course.

If counting left to right you start at 0. If counting right to left you start with -1.

Syntax for slicking is:

variable_name[start index : finish index]

The slice does not include the finish index.

Example:

my_string[0]

Would give the first character of the string.

my_string[0:]

Would give the entire string

my_string[9:12]

Would give characters 9 through eleven. Remember that counting starts at 0 and not 1

Type command

You can determine what data type a variable is with the type command.

Lets assume you have a variable named var. You can get what type of data is with the type command like this:

type(var)

And the class of data will be returned to you.

String Methods

https://docs.python.org/3/library/stdtypes.html#string-methods

Electrum

Install Electrum on Linux Mint 20.3

Install the pre-requisites for Electrum:

sudo apt install python3-setuptools python3-pyqt5 python3-pip libsecp256k1-0

This will pull in a bunch of dependencies as well. Say Yes.

Go to https://download.electrum.org/ and see what version is the latest version.
As of this writing the latest version is 4.2.1

Install the tar.gz file located in the latest version directory:

pip3 install https://download.electrum.org/4.2.1/Electrum-4.2.1.tar.gz

Add /home/mac/.local/bin to your path. Add this to the end of your ~/.bashrc file:

# Set your path to include $HOME/.local/bin
PATH="$HOME/.local/bin:$PATH

You can now simply run electrum from the command line like this:

$ electrum &

Documentation on Electrum is found here:

https://electrum.readthedocs.io/en/latest/index.html

Unofficial Guide:

https://bitcoinelectrum.com/

Using Electrum

BackUps

The unofficial guide suggests not backing up your wallet to cloud even though you have encrypted the wallet. They suggest backing up your wallet to a removable drive such as a flash drive.

Yes you can restore your wallet from your seed phrase but you cannot restore metadata from seed. By metadata I mean your transaction and address labels/descriptions and the addresses saved in your contact book. So backup your wallet every time you make a change to it.

Wallets are stored in:

~/.electrum/wallets

The idea of backups also includes the seed phrase written on a piece of paper. The guide suggests that it should not be stored only on a computer because hard drives fail. It should not be stored in the cloud as that could theoretically be compromised. The guide suggests it should strictly be stored on paper and suggests a notebook that you would not lose or throw away accidentally.

I’ve struggled with this idea. Take for example the idea of your house burning to the ground. You would lose both the notebook, the computer and any backups if not stored on the cloud. I suppose you could store the backup and paper in a fire proof safe.

I did a search for bitcoin cold storage on Amazon and found metal plates you can engrave with your seed. This might be the solution. None of them really say fireproof but if they were in a fireproof safe they might be safe. They appear to be made of aluminum and I suspect they might not survive a house burning down unless in a fireproof safe. There are versions made of titanium that can withstand 3000 degree temps.

Another option I have thought about would be to store the paper and backup offsite or in a different physical building. That brings in additional questions on how secure the offsite place is.

You can backup the wallet by going to:

File > Save Backup

I decided to put my wallet on my NFS share which with RAIDed drive redundancy.

Cryptocurrencies

Electrum only supports Bitcoin. I probably should have researched this earlier as it is now an exercise in futility since I need it to support multiple ccryptos.

Linux Convert Command

This command requires that the imagemagick package be installed.

sudo apt install imagemagick

To combine two single page pdf files into one multi-page pdf:

convert file1.pdf file2.pdf merged.pdf

 

More to come

Create a UEFI Linux Mint USB Installation Flash Drive

What you will need:

  • A USB flash drive big enough. A 4GB flash drive should be big enough.
  • The latest Linux Mint ISO image downloaded to your Windows box. I’m using version 19.3 for this.
  • Rufus. Preferably the latest version. As of this writing it is version 3.10.
  • Since Rufus is Windows software you will need a PC running Windows.

How to do it:

  1. Insert the USB drive. Determine what drive letter it is.
  2. Open Rufus. In the Device field choose your USB drive.
  3. In the Boot selection field select the ISO image for Linux Mint.
  4. For Partition scheme choose GPT.
  5. Choose NTFS for File System.
  6. Click the START button.
  7. You may see a pop up that asks you what mode to write. I have had better luck using DD image mode.
  8. You should then see a warning about overwriting the USB drive. If you are sure you can proceed.

To use the USB flash drive, insert it into the slot, reboot. When you see the splash screen hit F12 to get into boot options.
In my Dell PC I see a section that looks like this:

UEFI Boot:
        UEFI: SanDisk

Choose that to boot the Linux Mint installer OS.

IPTables

These are my notes on IP tables. Maybe at some point I may do a complete tutorial or How To but don’t hold your breath.

Chains:

There are typically 3 chains in a standard setup. They are:

INPUT
FORWARD
OUTPUT

Input is things coming into the server.
Forward are things that are forwarded by the server.
Output are things that are leaving the server.

Policies:

There is a default policy (rule) set up for each chain. CentOS somes standard with the default policy of ACCEPT for each of these chains. The command line to set the policy is like this:

# iptables -P INPUT ACCEPT

Pretty simple really. The -P is the flag to set the policy.

Flush:

The command that flushes the iptables is -F. This deletes the rules in the table.

# iptables -F

If changing rules from a remote host, the tutorial says to first put the INPUT policy to ACCEPT especially if you are going to flush the table. The flush command flushes everything except the default policy so if you have set it to ACCEPT then you won’t lock yourself out. Be sure to undo the ACCEPT on the INPUT policy or it will basically be wide open unless you have some other rule locking it down.

So the first two commands, accept on the input policy and flush on the table leave you with a pretty much blank rule set.

Saving:

It’s important to understand that the commands take effect immediately so if you do a wrong command you can lock yourself out. However they are not permanently stored until you save them with this:

# service iptables save

If you did lock yourself out then theoretically you could reboot the server before saving and it would revert back to whatever it was on the last save. I have not tested this yet but that is what I understand.

Showing:

You need to be able to see the results of your commands so you can show your tables like this:

iptables -L

This leaves a bit to be desired as it shows everything and may be too much information. This will show all Chains. If you just want to list one of the Chains you can do it like this:

# iptables -L [CHAIN]

For example:

# iptables -L INPUT

Even more useful is to list with Line Numbers. This is helpful if you want to insert a rule after a certain existing rule. That command looks like this:

# iptables -L --line-numbers

or

# iptables -L INPUT --line-numbers

Even better is using the -v or the verbose flag. That’s probably the best.

# iptables -L INPUT -v --line-numbers

Adding Rules:

Rules are added or deleted to the table by the -A or -D flag. The -A appends a rule and the -D deletes a rule. For example:

# iptables -A INPUT -i lo -j ACCEPT

This will allow everything to reach the lo interface. This is a good idea as programs running on the server interact with the lo interface.

By the way, the -i flag specifies an interface. The -j flag is the jump flag.  In the above example if something comes in (INPUT) on the lo interface, then jump to ACCEPT.

It is also important to note that rules are put into the table in the order they are typed in using the -A (append) command. You need to be sure you do not give permissions to something and then take it away later. It is also a good idea to set the policies for INPUT and FORWARD to drop then specifically set up the exceptions to this with the rules.

Deleting Rules:

The -D flag can be used with line numbers and is useful to delete specific lines in your IPTables config. The Delete command is done like this:

# iptables -D INPUT 4

In other words, deleting from the INPUT chain rule number 4.

Inserting Rules:

Rules need to be in certain orders or you could cause problems. You can insert a rule to the table with this:

# iptables -I INPUT 3 -p tcp --dport 23 -j ACCEPT

This inserts at line 3 the rule to accept telnet in the INPUT chain.

IP Addresses:

You can also specify IP addresses in a rule. For example if I wanted to specify that I wanted to accept connections coming from a certain source IP address I would use something like this:

# iptables -A INPUT -s 192.168.0.4 -j ACCEPT

The -s means source IP.

You can also specify entire networks like this:

# iptables -A INPUT -s 192.168.0.0/24 -j ACCEPT

Comments:

Comments can also be added. This is useful if you are putting the lines into a script or something. Everything after the “#” is ignored.

# iptables -A INPUT -s 192.168.0.0/24 -j ACCEPT  # using standard slash notation

Mac Addresses:

You can also filter by mac addresses in a rule. Something like this:

# iptables -A INPUT -m mac --mac-source 00:26:B9:D1:D9:6B -j ACCEPT

Anything from the specified source mac address will be accepted by the above rule.

You can also add an IP address as well as a mac address for further filtering:

# iptables -A INPUT -s 192.168.0.4 -m mac --mac-source 00:50:8D:FD:E6:32 -j ACCEPT

The above will append the rule to the end of the chain. It is probably better to insert it somewhere like this:

# iptables -I INPUT 75 -s 192.168.0.4 -m mac --mac-source 00:50:8D:FD:E6:32 -j ACCEPT

Protocols & Ports:

To further refine you really need protocols and ports defined in a lot of the rules. Going back to this example:

# iptables -I INPUT 3 -p tcp --dport 23 -j ACCEPT

The -p means protocol, in this case TCP and the --dport means destination port, in this case port 23 or telnet.

To get more granular on the rules you will want to put them together. For ecample I want to accept on the INPUT chain connections coming from 192.168.0.0/24 and port 23 or telnet. The rule would look like this:

# -A INPUT -s 192.168.0.0/24 -p tcp --dport 23 -j ACCEPT

Drop & Reject:

The default configuration of IP Tables for CentOS is to have the INPUT, FORWARD & OUTPUT policies set to ACCEPT. This is probably not a good idea. Depending on your security posture it might be OK for your OUTPUT policy, unless you want to limit what goes out of your system. The way you solve this issue is to add some REJECT rules to the end of your configs. A REJECT rule looks something like this:

# iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited
# iptables -A FORWARD -j REJECT --reject-with icmp-host-prohibited

A REJECT will send a TCP Reject whereas a DROP simply drops the connection. Depending on your security posture a DROP might be a better decision.

States:

The State Match

The most useful match criterion is supplied by the `state’ extension, which interprets the connection-tracking analysis of the `ip_conntrack’ module. This is highly recommended.

Specifying `-m state’ allows an additional `–state’ option, which is a comma-separated list of states to match (the `!’ flag indicates not to match those states). These states are:

NEW: A packet which creates a new connection.
ESTABLISHED: A packet which belongs to an existing connection (i.e., a reply packet, or outgoing packet on a connection which has seen replies).
RELATED: A packet which is related to, but not part of, an existing connection, such as an ICMP error, or (with the FTP module inserted), a packet establishing an ftp data connection.
INVALID: A packet which could not be identified for some reason: this includes running out of memory and ICMP errors which don’t correspond to any known connection. Generally these packets should be dropped.

An example of this powerful match extension would be:

# iptables -A FORWARD -i ppp0 -m state ! --state NEW -j DROP

The default iptables configuration has the ESTABLISHED and RELATED states set to ACCEPT on the INPUT chain like this:

# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Probably a good idea to keep that and put it first in the list. This will keep any connections going that have already been established. For example if you have an ssh connection going and you change the iptables for SSH and lock yourself out the connection will remain until you close the connection. This has saved me at least once but you could potentially keep bad connections going as well so use with care.

I have also seen that it is a good idea to use states with regular rules like this:

# iptables -A INPUT -s 192.168.0.0/24 -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT

I don’t completely understand it myself. Things should work without it. I’ve just seen posts about it and think it is useful to mention here.

Another good thing to use might be the INVALID state. INVALID means a packet that could not be identified somehow. Just drop them:

# iptables -A INPUT -m state --state INVALID -j DROP
# iptables -A FORWARD -m state --state INVALID -j DROP
# iptables -A OUTPUT -m state --state INVALID -j DROP

Script:

Here’s a little script that sets up pretty much what I talked about on this page:

#!/bin/bash

# iptables example configuration script
# Flush all current rules from iptables
 iptables -F

# Set default policies for INPUT, FORWARD and OUTPUT chains
 iptables -P INPUT DROP
 iptables -P FORWARD DROP
 iptables -P OUTPUT ACCEPT

# Drop invalid packets
 iptables -A INPUT -m state --state INVALID -j DROP
 iptables -A FORWARD -m state --state INVALID -j DROP
 iptables -A OUTPUT -m state --state INVALID -j DROP

# Accept packets belonging to established and related connections
 iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow private lan to ping
 iptables -A INPUT -s 192.168.0.0/24 -p icmp -j ACCEPT

# Set access for localhost
 iptables -A INPUT -i lo -j ACCEPT

# Allow private lan to ssh
 iptables -A INPUT -s 192.168.0.0/24 -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT

# Save settings
 /sbin/service iptables save

# List rules
 iptables -L -v --line-numbers

 

Validate a Certificate’s Chain

You can validate a Certificate’s chain by extracting the Authority Key Identifier from the cert like this:

$ openssl x509 -text -in [cert-name].crt | grep -A 1 "Authority Key Identifier"

You should get a result similar to this:

X509v3 Authority Key Identifier: keyid:FC:8A:50:BA:9E:B9:25:5A:7B:55:85:4F:95:00:63:8F:E9:58:6B:43

This is the Key Identifier from the Intermediate Cert. This should match up with the “Subject Key Identifier” of the Intermediate Cert.

Get the “Subject Key Identifier” of the Intermediate Cert:

$ openssl x509 -text -in [intermediate-cert-name].crt | grep -A 1 "Subject Key Identifier"

You should get a result similar to this:

X509v3 Subject Key Identifier: FC:8A:50:BA:9E:B9:25:5A:7B:55:85:4F:95:00:63:8F:E9:58:6B:43

If the two identifiers match then you have the correct Intermediate Cert for the Cert.

You can now repeat the process with the Intermediate Cert and the root Cert and validate that the root cert you have is the one for the Intermediate.

The tr command

The tr command:

It’s short for “translate” but might be easier to remember thinking of it as “truncate”. The man page has this to say about it:

DESCRIPTION
Translate, squeeze, and/or delete characters from standard input, writing to standard output.

There are probably books written on what tr can do. I’m just going to leave some notes here on how I typically use it.

The tr program reads from standard input and writes to standard output.

Convert multiple lines of text into a single line of text:

Consider a file named file containing the following data:

abcde
fghij
klmno
pqrst
uvwxy

You want to convert the multiple lines into a single line of text. You can do that using tr with something like this:

$ cat file | tr -d '\n'

The result of the command is written to standard output as:

abcdefghijklmnopqrstuvwxy

The -d option deletes. In this case we’re deleting the newline character.

Replace comma with newline:

Sometimes you need to convert a single delimited line to multiple lines. Consider the following file named file containing the following data:

abcde,fghij,klmno,pqrst,uvwxy

We can translate the comma in the file into a new line character with the following command:

$ cat file | tr ',' '\n'

The results look like this:

abcde
fghij
klmno
pqrst
uvwxy

 

 

Convert PEM certificate to PFX or P12

How to convert a PEM certificate to PFX or P12 format.

The PFX or PKCS12 format is a binary format that stores a server certificate, any intermediate certificates, along with the private key into a single encrypted file. PFX files typically have the .pfx and .p12 extensions. PFX files are typically used on Windows machines and macOS machines to import and export certificates and private keys. Tomcat currently operates only on JKS, PKCS11 or PKCS12 format keystores. The JKS format is Java’s standard “Java KeyStore” format, and is the format created by the keytool command-line utility. The PKCS12 format is an internet standard, and can be created with OpenSSL.

What you’ll need:

  • You will need the private key that was used to create the public key and certificate.
  • You will need the certificate in PEM format, typically with file extension of .crt, .pem or .cer.
  • You will need Openssl.

Lets take a look at the Openssl command you would use to convert the PEM cert to PFX:

openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile chain.crt

Lets break down the different parts of the command to see what they do:

openssl – This starts the openssl software.

pkcs12 – This tells openssl to use PKCS#12 Data Management.

-export -out certificate.pfx – This tells openssl to export out a PFX file named certificate.pfx.

-inkey privateKey.key – This tells openssl to import the private key from a file named privateKey.key.

-in certificate.crt – This tells openssl to import the certificate from a file named certificate.crt.

-certfile chain.crt – This tells openssl to include any additional certificates contained in chain.crt you want to include in the PFX file. Typically this would be any Intermediate Certs that chain your cert to a root cert.

After you enter this command you will be prompted for a password that protects the PFX file. Without the password the PFX file is useless so do not forget it.

The end result of this command will be that you have a new file named certificate.pfx which contains your Private Key, the Certificate and any Intermediate certs you added as well, all wrapped into a binary format and protected by a password.