Commit 04685d4b authored by Clark's avatar Clark

Adding everything... will recreate this repo for Grand Reopening

parent f7477b5a
This diff is collapsed.
# -*- org-confirm-babel-evaluate: nil -*-
#+TITLE: Bastion Host
#+DATE: 11/5/2019
#+TAGS: :blog:guides:opnsense:firewall:bastion:pcengines:apu:
#+DESCRIPTION:
#+PROPERTY: header-args :cache yes
#+BEGIN_VERSE
This post describes how to setup a Bastion host using OPNsense OS on PC Engines APU hardware.
#+END_VERSE
* Overview
This device will serve as a perimeter router and firewall specified in the below diagram.
#+begin_src plantuml :file img/Bastion_Host.svg
' Specifying aesthetics
skinparam backgroundColor #FFF
skinparam shadowing false
skinparam defaultFontColor #404040
skinparam defaultFontSize 24
skinparam linetype polyline
skinparam frame {
backgroundColor #FEFECE
borderColor #53485C
}
skinparam node {
backgroundColor #FEFECE
borderColor #53485C
}
skinparam rectangle {
backgroundColor<< Public Zone >> #FFE5E5
borderColor<< Public Zone >> #FF4C4C
backgroundColor<< DMZ >> #FFF6E5
borderColor<< DMZ >> #FFC04C
backgroundColor<< Private Zone >> #E5F2E5
borderColor<< Private Zone >> #46A64C
borderColor<< OpenNet >> #FF7F7F
backgroundColor<< OpenNet >> #FFF
borderThickness<< OpenNet >> 8
borderColor<< FastNet >> #FFD27F
borderThickness<< FastNet >> 8
borderColor<< FreeNet >> #7FBF7F
borderThickness<< FreeNet >> 8
}
skinparam control {
borderColor #53485C
}
skinparam component {
borderColor #53485C
}
skinparam cloud {
borderColor #53485C
}
skinparam package {
backgroundColor AliceBlue
borderColor #53485C
}
' Define the network components
rectangle << Public Zone >> {
cloud Internet {
control "0.0.0.0/0" as 0.0.0.0
}
database "<b>Modem" as Modem
}
control "172.31.0.1/32" as 172.31.0.1_32
node "<b>Bastion Host</b>\n\
Router & Firewall\n\
OS: [[https://opnsense.org/ OPNsense]]\n\
[[https://www.pcengines.ch/apu2e4.htm PC Engines APU.2E4]]" as Bastion
rectangle << DMZ >> {
database "<b>Switch" as Switch
control "172.22.132.0/29" as 172.22.132.0_29
}
rectangle << Private Zone >> {
control "172.27.0.0/30" as 172.27.0.0_30
node "<b>Internal Firewall" as Firewall
}
' Define the network connections
'left to right direction
0.0.0.0 -[thickness=3,#53485C]right- Modem
Modem -[thickness=3,#53485C]- 172.31.0.1_32
Bastion -[thickness=3,#53485C]left- 172.31.0.1_32 : 172.31.0.1
Bastion -[thickness=3,#53485C]down- 172.27.0.0_30 : 172.27.0.1
172.27.0.0_30 -[thickness=3,#53485C]left- Firewall
Bastion -[thickness=3,#53485C]up- 172.22.132.0_29 : 172.22.132.1
172.22.132.0_29 -[thickness=3,#53485C]right- Switch
#+end_src
#+RESULTS[088952ba84a786da42ca6ab765fef344e3f6c6fe]:
[[file:img/Bastion_Host.svg]]
_Procedure_:
1) Flash the OPNsense OS to an mSATA drive
2) Mount the mSATA on the APU board
3) Attach a remote session using a null modem cable
4) Configure the OPNsense OS
** Prerequisites
Hardware is required to host the operating system. I've chosen to go with [[https://www.pcengines.ch/apu2e4.htm][PC Engines APU 2E4]] board. There are multiple storage options on the APU boards - I've chosen to utilize the mSATA bus to attach a storage drive.
Since the PC Engines APU boards lack a display adapter, the best option to send commands to the APU board is via the serial port. A =null modem cable= is required to send commands to the APU via the serial port.
* Flash OPNsense to mSATA
Download the OPNsense amd64 serial console image and validate the checksum against those posted on the [[https://opnsense.org/download/][OPNsense Download page]]. The below =wget= downloads the latest image (20.1 as of this writing) from the dns-root.de mirror.
#+begin_example sh
wget --https-only --secure-protocol=PFS https://mirror.dns-root.de/opnsense/releases/20.1/OPNsense-20.1-OpenSSL-nano-amd64.img.bz2
sha256sum OPNsense-20.1-OpenSSL-nano-amd64.img.bz2
#+end_example
Attach an mSATA drive to the machine with the OPNsense image, and flash the image to the disk. Here, my mSATA is mounted on =/dev/sda=
#+begin_example sh
bzip2 -d OPNsense-20.1-OpenSSL-nano-amd64.img.bz2
# First I format the disk and ensure all bits are zero (this takes long)
sudo dd if=/dev/zero of=/dev/sda status=progress
sudo dd if=OPNsense-20.1-OpenSSL-nano-amd64.img of=/dev/sda status=progress
# Eject the mSATA drive
sudo eject /dev/sda
#+end_example
After ejecting the mSATA from the machine, physically attach it to the PC Engines APU mSATA connector. Do not power it on yet.
* OPNsense Configuration
In order to configure the OPNsense OS, I need to connect to the serial console on the APU from my host. I use =minicom= for this purpose.
** Minicom Configuration
I've had more success with *minicom* over *screen* for connecting to the serial console on the APU. Install using =sudo apt install minicom=.
Unless other USB devices are mounted, the APU will likely appear on =/dev/ttyUSB0=. In order to send keys from the remote host to the APU, I disable /Hardware Flow Control/ in the *minicom* /Serial port setup/ using =sudo minicom -s=. I save the below setup to my defaults.
[[file:img/Minicom_Default_Setup.png]]
Thereafter, start a *minicom* session simply using =sudo minicom=. It's a good idea to perform a loopback test before attaching to the APU by inserting a paperclip in pins 2 and 3 on the serial adapter. After doing so, I can verify send keys are echoed in the *minicom* console. This is the first troubleshooting step to attempt if having problems connecting to the serial console.
When needing to exit =minicom=, I use the key combination: =CTRL-A Z= to access special commands, then =X= to exit.
** OPNsense Installation
Before powering on the APU, ensure each of the NICs are plugged in and connect to the serial port to the remote host, and create a *minicom* session using =sudo minicom=. Then power on the APU. Immediately some BIOS messages should appear in the *minicom* console, and then the GNU Grub bootloader with automatically appear.
The OPNsense initial boot will take *long*, especially the /super-block backups/ if you have a large mSATA drive. It's safe to walk away and come back to the login screen - then OPNsense will automatically assign the NICs, incorrectly. You'll have to login and reassign them. Chose /not/ to configure VLANs. Then assign the interfaces as follows:
| Zone | Interface |
|------+-----------|
| WAN | igb2 |
| LAN | igb0 |
| OPT1 | igb1 |
Wait for initial installation to complete.
* TODO OPNsense Configuration
Login with the username =root= and password =opnsense=. Enter option =2= to set interface IP address.
Configure the LAN interface as follows:
| Option | Configuration |
|------------------------------+---------------|
| Configure via DHCP | n |
| LAN IPv4 Address | 172.27.0.1 |
| LAN IPv4 subnet bit count | 30 |
| LAN upstream gateway address | none |
| Configure IPv6 via WAN/DHCP | n |
| LAN IPv6 Address | none |
| Enable DHCP server on LAN | y |
| start address of IPv4 | 172.27.0.2 |
| end address of IPv4 | 172.27.0.254 |
| revert to HTTP? | n |
Configure the OPT1 interface as follows:
| Option | Configuration |
|-------------------------------+---------------|
| Configure via DHCP | n |
| OPT1 IPv4 Address | 172.22.132.1 |
| OPT1 IPv4 subnet bit count | 29 |
| OPT1 upstream gateway address | none |
| Configure IPv6 via WAN/DHCP | n |
| OPT1 IPv6 Address | none |
| Enable DHCP server on OPT1 | n |
| start address of IPv4 | 172.27.0.2 |
| end address of IPv4 | 172.27.0.254 |
| revert to HTTP? | n |
Thereafter, the OPNsense Web GUI will be accessible at https://172.27.0.1 from the LAN zone with the default firewall settings.
** TODO Access Control
- Setup CA
- Setup users with certs
- Setup TOTP Auth server
** TODO Firmware
- Updates
- Checks
- Audit: Security and Health
*** Update BIOS
I deployed v4.11.0.6, from https://pcengines.github.io/#mr-34
From a minicom session, login as root. Then run below, one step at a time.
#+BEGIN_SRC sh
curl -O https://3mdeb.com/open-source-firmware/pcengines/apu2/apu2_v4.11.0.6.rom
pkg install -y flashrom
flashrom -w apu2_v4.11.0.6.rom -p internal:boardmismatch=force
#+END_SRC
Then reboot the router.
** TODO Basic Networking
*** DNS
Unbound DNS is the default DNS service. Enable DNSSec in the general settings at https://172.27.0.1/services_unbound.php. In the advanced settings at https://172.27.0.1/services_unbound_advanced.php, I enable the following flags and options:
| Key | Value |
|--------------------------+---------|
| Hide Identity | Enabled |
| Hide Version | Enabled |
| Prefetch Support | Enabled |
| Prefetch DNS Key Support | Enabled |
| Harden DNSSEC data | Enabled |
| Log leve verbosity | Level 4 |
| Extended statistics | Enabled |
| Log Queries | Enabled |
I use defaults for the rest of the Unbound DNS config.
*** DHCP
- DHCP
*** Firewalls
*** Proxy
**
# -*- org-confirm-babel-evaluate: nil -*-
#+TITLE: Internal Firewall
#+DATE: 11/5/2019
#+TAGS: :blog:guides:ipfire:firewall:pcengines:apu:
#+DESCRIPTION:
#+PROPERTY: header-args :cache yes
#+BEGIN_VERSE
This post describes how to bootstrap an Internal Firewall on the IPFire OS using PC Engines APU hardware.
#+END_VERSE
* Overview
This device will serve as the Internal Firewall specified in the below diagram. The device will be used primarily for traffic shaping, and to segment a secure private zone away from a lower-latency zone which may also include guests.
#+begin_src plantuml :file img/Internal_Firewall.svg
' Specifying aesthetics
skinparam backgroundColor #FFF
skinparam shadowing false
skinparam defaultFontColor #404040
skinparam defaultFontSize 24
skinparam linetype polyline
skinparam frame {
backgroundColor #FEFECE
borderColor #53485C
}
skinparam node {
backgroundColor #FEFECE
borderColor #53485C
}
skinparam rectangle {
backgroundColor<< Public Zone >> #FFE5E5
borderColor<< Public Zone >> #FF4C4C
backgroundColor<< DMZ >> #FFF6E5
borderColor<< DMZ >> #FFC04C
backgroundColor<< Private Zone >> #E5F2E5
borderColor<< Private Zone >> #46A64C
borderColor<< OpenNet >> #FF7F7F
backgroundColor<< OpenNet >> #FFF
borderThickness<< OpenNet >> 8
borderColor<< FastNet >> #FFD27F
borderThickness<< FastNet >> 8
borderColor<< FreeNet >> #7FBF7F
borderThickness<< FreeNet >> 8
}
skinparam control {
borderColor #53485C
}
skinparam component {
borderColor #53485C
}
skinparam cloud {
borderColor #53485C
}
skinparam package {
backgroundColor AliceBlue
borderColor #53485C
}
' Define the network components
rectangle << OpenNet >> {
node "<b>Bastion Host</b>" as Bastion
}
rectangle << Private Zone >> {
control "172.27.0.0/30" as 172.27.0.0_30
node "<b>Internal Firewall \n\
OS: [[https://www.ipfire.org IPFire]]\n\
[[https://www.pcengines.ch/apu2e4.htm PC Engines APU.2E4]]" as Firewall
rectangle << FreeNet >> {
control "172.22.133.128/25" as 172.22.133.128_25
database "<b>Tor Bridge</b>" as Tor_Bridge
}
rectangle << FastNet >> {
control "172.22.133.0/25" as 172.22.133.0_25
database "<b>Orbi WiFi Bridge</b>" as Orbi_Bridge
}
}
' Define the network connections
'left to right direction
Bastion -[thickness=3,#53485C]left- 172.27.0.0_30 : 172.27.0.1
172.27.0.0_30 -[thickness=3,#53485C]left- Firewall : 172.27.0.2
Firewall -[thickness=3,#53485C]down- 172.22.133.128_25 : 172.22.133.254
172.22.133.128_25 -[thickness=3,#53485C]right- Tor_Bridge
Firewall -[thickness=3,#53485C]up- 172.22.133.0_25 : 172.22.133.2
172.22.133.0_25 -[thickness=3,#53485C]right- Orbi_Bridge
#+end_src
#+RESULTS[a8401dfa1771fbc5ac7adf98ba6b29ba81f0cfc8]:
[[file:img/Internal_Firewall.svg]]
_Procedure_:
1) Flash the IPFire OS to an mSATA drive
2) Mount the mSATA on the APU board
3) Attach a remote session using a null modem cable
4) Configure the IPFire OS
** Prerequisites
Hardware is required to host the operating system. I've chosen to go with [[https://www.pcengines.ch/apu2e4.htm][PC Engines APU 2E4]] board. There are multiple storage options on the APU boards - I've chosen to utilize the mSATA bus to attach a storage drive.
Since the PC Engines APU boards lack a display adapter, the best option to send commands to the APU board is via the serial port. A =null modem cable= is required to send commands to the APU via the serial port.
* Flash IPFire to mSATA
Download the IPFire headless image and validate the checksum against those posted on the [[https://www.ipfire.org/download/ipfire-2.25-core141][IPFire 2.25 Download page]]. As of this writing, 2.25 is the latest build. Future releases should be reflected at https://www.ipfire.org/download.
#+begin_example sh
wget --https-only --secure-protocol=PFS https://downloads.ipfire.org/releases/ipfire-2.x/2.25-core141/ipfire-2.25.2gb-ext4.x86_64-full-core141.img.xz
sha256sum ipfire-2.25.2gb-ext4.x86_64-full-core141.img.xz
#+end_example
Attach an mSATA drive to the machine with the IPFire image, and flash the image to the disk. Here, my mSATA is mounted on =/dev/sda=
#+begin_example sh
unxz -v ipfire-2.25.2gb-ext4.x86_64-full-core141.img.xz
# First I format the disk and ensure all bits are zero (this takes long)
sudo dd if=/dev/zero of=/dev/sda status=progress
sudo dd if=ipfire-2.25.2gb-ext4.x86_64-full-core141.img of=/dev/sda status=progress
# Eject the mSATA drive
sudo eject /dev/sda
#+end_example
After ejecting the mSATA from the machine, physically attach it to the PC Engines APU mSATA connector. Do not power it on yet.
* IPFire Configuration
In order to configure the IPFire OS, I need to connect to the serial console on the APU from my host. I use =minicom= for this purpose.
** Minicom Configuration
I've had more success with *minicom* over *screen* for connecting to the serial console on the APU. Install using =sudo apt install minicom=.
Unless other USB devices are mounted, the APU will likely appear on =/dev/ttyUSB0=. In order to send keys from the remote host to the APU, I disable /Hardware Flow Control/ in the *minicom* /Serial port setup/ using =sudo minicom -s=. I save the below setup to my defaults.
[[file:img/Minicom_Default_Setup.png]]
Thereafter, start a *minicom* session simply using =sudo minicom=. It's a good idea to perform a loopback test before attaching to the APU by inserting a paperclip in pins 2 and 3 on the serial adapter. After doing so, I can verify send keys are echoed in the *minicom* console. This is the first troubleshooting step to attempt if having problems connecting to the serial console.
When needing to exit =minicom=, I use the key combination: =CTRL-A Z= to access special commands, then =X= to exit.
** IPFire Installation
Before powering on the APU, connect to the serial port to the remote host, and create a *minicom* session using =sudo minicom=. Then power on the APU. Immediately some BIOS messages should appear in the *minicom* console, and then the GNU Grub bootloader with automatically appear. There should be three options, select *IPFire* over the /Serial Console/.
[[file:img/Bootloader_IPFire_Serial.png]]
Wait patiently for initialization, potentially including a reboot. After reboot, if the /Serial Console/ option is not present, select the normal *IPFire* GRUB entry.
Proceed with installation. The serial console display requires a discerning eye, because the cursor location is ambiguous. It's not difficult to determine where the cursor is by using arrow keys and tab to experiment. For example, in the below screenshot, I've actually selected =us=, although you could not tell this by observing the screenshot alone, without having scrolled around first.
[[file:blog.bytecache.io/content/Bare-Metal/img/Serial_Console_Quirk.png]]
The [[https://wiki.ipfire.org/installation][IPFire Installation Handbook]] is very helpful for additional context and guidance while going through the installation steps (particularly the network setup step).
By convention, I set the APU interfaces to *IPFire* /zones/ as follows.
| IPFire Zone | APU Interface |
|-------------+-----------------|
| Green | [higher bytes]4 |
| Orange | [higher bytes]5 |
| Red | [higher bytes]6 |
After logging in, to gracefully shutdown the device, use =shutdown -h now=. Do /not/ shutdown by removing the power supply. The APU is powered down once all the lights are off - then it is safe to remove the power supply.
* TODO IPFire Configuration
Access the IPFire UI at https://172.22.133.254:444 by default, using the credentials specified during installation.
** TODO Add SSH key to ~/.ssh/config, yada yada
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
# -*- org-confirm-babel-evaluate: nil -*-
#+TITLE: Block Ciphers
#+DATE: 11/30/2019
#+TAGS: :blog:guides:cryptanalysis:cryptography:ciphers:block:
#+DESCRIPTION:
#+PROPERTY: header-args :cache yes
#+HTML_HEAD_EXTRA: <style type="text/css">th {font-weight: normal;}</style>
*Block ciphers* use *pseudo random permutations (PRP)* to encrypt fixed-length /block/ messages such that the ciphertext space, $\mathscr{C}$, is equivalent to the message space, $\mathscr{M}$.
* TODO Key Expansion
:PROPERTIES:
:CUSTOM_ID: Key_Expansion
:END:
* TODO Pseudo Random Permutations
:PROPERTIES:
:CUSTOM_ID: Pseudo_Random_Permutations
:END:
* TODO Invertability
:PROPERTIES:
:CUSTOM_ID: Invertability
:END:
The *PRP* must be invertable using a symmetric key. The most pervasive *PRP* is the *Fiestal network*...
*Block ciphers* reuse the symmetric key to encrypt data that is larger than the fixed block size.
* TODO Exhaustive Search
:PROPERTIES:
:CUSTOM_ID: Exhaustive_Search
:END:
# -*- org-confirm-babel-evaluate: nil -*-
#+TITLE: Pseudo Random Generators
#+DATE: 11/28/2019
#+TAGS: :blog:guides:cryptanalysis:cryptography:ciphers:stream:prg:predictability:semanticsecurity:
#+DESCRIPTION:
#+PROPERTY: header-args :cache yes
#+HTML_HEAD_EXTRA: <style type="text/css">th {font-weight: normal;}</style>
In order to relax key length constraints necessary for *perfect secrecy*, a *pseudo random generators (PRGs)* can be used to achieve /pretty good/ secrecy.
A *PRG* is an efficient deterministic function, $\mathscr{G}$, that maps the smaller seed space to the key space. $\mathscr{G}: \{0,1\}^s \rightarrow \{0,1\}^n$, where $n \gg s$.
* Predictability
:PROPERTIES:
:CUSTOM_ID: Predictability
:END:
In order to be secure, a *PRG* must _not_ be *predictable*. A *PRG* is considered *predictable* if there exists an efficient algorithm, $\mathscr{A}$, which satisfies the following:
#+BEGIN_LATEX
\begin{equation}\label{predictability}
\underset{k \xleftarrow{R} \mathscr{K}}{Pr}[ \mathscr{A}(\mathscr{G}(k))|_{1,...,i} = \mathscr{G}(k)|_{i+1} ] \geq \frac{1}{2} + \varepsilon,\\
\textrm{where } \varepsilon \textrm{ is positive and non-negligible}
\end{equation}
#+END_LATEX
* Statistical Tests
:PROPERTIES:
:CUSTOM_ID: Statistical_Tests
:END:
In addition to not being *predictable*, a PRG should generate output that is indistinguishable from the uniform distribution over ${\{0,1\}}^n$. *Statistical tests* are used to assess indistinguishability for PRGs. *Statistical tests* are arbitrarily defined based on to validate the underlying data structure. For example, with binary data, the count of =0='s in an array should be roughly equal to the count of =1='s. To test this, one could perform a *statistical test*, $\mathscr{A} (x)$, on a sample of PRG output, $x$, to check whether $| count(0) - count(1) | \leq 10 * \sqrt{n}$. When satisfied, the *statistical test* outputs 1 (i.e., the PRG data violates randomness properties of the underlying data structure).
There is no limit to the number of conceivable statistical tests, nor is there a quantity of statistical tests which equate to good security. Rather, statistical tests are more useful for proving /insecurity/.
* Advantage
:PROPERTIES:
:CUSTOM_ID: Advantage
:END:
*Advantage* quantifies the power of a *statistical test* by comparing the performance using *PRG* input versus using /truly random/ input.
#+BEGIN_LATEX
\begin{equation}\label{advantage}
Adv_{PRG}[\mathscr{A}, \mathscr{G}] = \left| Pr[\mathscr{A}(\mathscr{G}(k)) = 1] - Pr[\mathscr{A}(r) = 1] \right|
\end{equation}
#+END_LATEX
If a *statistical test* performs the same regardless of input, the *advantage* is nil. However, if the *advantage* is close to 1, then the *statistical test* has broken the PRG, $\mathscr{G}$.
* Semantic Security
:PROPERTIES:
:CUSTOM_ID: Semantic_Security
:END:
The concept of *semantic security* helps define a feasible level of security attainable by PRGs, since they cannot achieve *[[file:Stream_Ciphers.org::#Perfect_Secrecy][perfect secrecy]]*. *Semantic security* simply requires that the distributions of ciphertext for two different messages be computationally indistinguishable (denoted $\approx_p$) for all messages the attacker can exhibit. This can be assessed by determining the advantage of adversary A over encryption algorithm E, for example:
#+BEGIN_LATEX
\begin{equation}\label{semantic_security}
{\bf E} \textrm{ is } {\bf semantically} \textrm{ } {\bf secure} \textrm{ if } \forall {\it efficient} \textrm{ attackers, } {\bf A}: \\
Adv_{SS}[{\bf A}, {\bf E}] \textrm{ is } {\it negligible} \\
\Rightarrow \forall \textrm{ explicit } m_0 , m_1 \in \mathscr{M}: \quad {\bf { E(k,m_0 ) } \approx_p { E(k,m_1 ) } }
\end{equation}
#+END_LATEX
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment