Simple Linux (Ubuntu) Security

I’m setting up a Bitcoin full node to perform some analyses on the full blockchain. Here are quick steps I followed to improve the security of a basic Ubuntu box for these purposes [1]. This is not meant to be an exhaustive list! Rather, this should serve as a general approach that helps you think about how you can continue to improve and monitor the security of the systems you’re using. And, while I’m using Ubuntu, these general principles apply to other Linux distros, too.

  1. Step 1: Use What You Know
  2. Step 2: Run The Bare Necessities
  3. Step 3: Filter Communications
  4. Step 4 – ∞: Update & Monitor
  5. Final Step: I Give You… THE INTERNET!

Step 1: Use What You Know

When I was younger, I remember someone suggesting to my father that he could use a simpler tool to test a TV component instead of the oscilloscope he was already using. However, he promptly replied, “I like to use what I know best,” and he just kept using the oscilloscope. This wisdom applies to the security realm, too.

My first step towards configuring a full node involves ditching Windows. This shouldn’t be a interpreted as an indictment against the possible security of Windows. Rather, I don’t know Windows security as well as I know Linux security, and I should stick with what I know best. And, I chose Ubuntu because I’ve used this distro the most over the past year. [Note to future self: remember that for some reason burning DVDs at any of the faster speeds on my iMac leads to images that can’t be mounted 🙁 ]

Step 2: Run The Bare Necessities

Sure, with Ubuntu, you can have it all… but just know ALL includes possible vulnerabilities, too. When I install Ubuntu for this type of purpose, I first start by installing the “Minimum Install,” an option that some other distros offer, too. Once installed, I follow the steps below to remove more unneeded stuff (“stuff” is a technical term that is often under-appreciated, but not here, my friends, not here.)

  1. Run the command below to view the running processes:
    # sudo lsof -i
  2. Identify a process that seems unneeded (e.g., cups, avahi-daemon, etc.)
  3. Remove the package using the command below [2]:
    # sudo apt-get autoremove cups
  4. Restart the computer and make sure there are no errors.
  5. Rinse and repeat until the song above plays like an anthem when I view the processes.

Step 3: Filter Communications

“Pardon me, do you have any Grey Poupon?”

I’ve learned to filter communications on social media with some people so I can avoid drama… not you, of course [note to self…]. In the same way, helping computers filter communications can help limit your system administration drama.

I’ve learned to love iptables, and so can you. As in any relationship, it first starts by listening… figuratively and literally. Often, when you run the command below, you’ll see that iptables is overly ACCEPTing in terms of communications (oh, Ubuntu, how quaint):
# sudo iptables -S

This is one situation in which it’s preferable NOT to be accepting. In fact, in order to prioritize security, we start by blocking everything, and then we explicitly accept what we absolutely need (e.g., port 80 for apt-get, port 53 for DNS, etc.) There are plenty of tutorials on iptables out there (e.g., here, here, and here), but hopefully these principles point you in the general direction so you can get started [3].

Steps 4 – ∞: Update & Monitor

“I can’t wait to share this hour-long video on social media… repeatedly.”

New parents know the joy of bringing home a new baby to the nursery that they’ve carefully prepared. Every little detail in the room has been painstakingly considered. New parents also quickly realize that the easy work was preparing the room. Every new day going forward requires constant updates and monitoring (e.g., new diapers, new clothes, new furniture, new diap… whoops, sorry, I was dreaming of sleep and forgot I already said… zzzzzzzzzz…)

In the same way, our precious new Ubuntu box will require constant updates and monitoring. If you study pen-testing techniques, you’ll quickly realize a common theme: exploits are old! Unless you’re up against an incredibly brilliant hacker or powerful nation state, the hackers attacking your system are searching for vulnerabilities in software that have already been patched. If you diligently update your system, you can avoid the vast majority of exploits that could be used against your baby. It’s simple:
# sudo apt-get update
# sudo apt-get upgrade

Finally, because you know your little baby better than anyone else, because you’ve limited your system to the bare necessities, because you’ve filtered your communications, and because you’ve diligently updated your system, you can sometimes identify zero-day exploits (and mitigate them) before there’s even a patch (all zero-days have to transition to one-days somehow, and you could be the one!) Monitoring the logs and noticing suspicious activity on a well-secured system is much easier because there is less to see: nefarious behavior that is new will stand out. Stay vigilant, my friends!

Final Step: I Give You… THE INTERNET!

You’re ready to let your little baby go out into the world [4]. Fair thee well!

All-Time Classic!


  1. You will often hear of hardening a system to reduce the attack surface for a specific use. I hate this term, because a “hardened” system soon becomes soft and squishy if it’s not actively updated and monitored and improved. Remember, security is a process, not a product.
  2. There are various ways to remove packages using apt-get. I use the autoremove option because it automatically removes associated dependencies, too, if they are otherwise unused.
  3. Remember, rules are ephemeral unless you take steps to make them persistent. New users are often surprised to see their configuration work disappear when they next reboot. I like to use a combination of the iptables-persistent package and the iptables-save command to make my rules persistent.
  4. There are certainly other things one can (and should) do, such as contain the possible damage apps/processes can do to the rest of the system, but I’ll cover these approaches in a later post.

Mnemonic For OSI Model Layers

There are a million acronyms out there to help students remember the layers of the Open Systems Interconnection (OSI) model. Why offer another? Well, this one has worked best for me.

As a reminder, the OSI Model Layers are as follows:

  • Layer 7: Application
  • Layer 6: Presentation
  • Layer 5: Session
  • Layer 4: Transport
  • Layer 3: Network
  • Layer 2: Data Link
  • Layer 1: Physical

AP(p)S Transport Network Data Physical(ly)

I like this because it helps me remember several important pieces of information in one tidy little phrase.

  1. The Transport, Network, Data (link), and Physical layers are spelled right out.
  2. Grouping Application, Presentation, and Session together into the acronym AP(p)S helps group the upper layers together, and it conveys that these layers are of primary concern for the application-level data.
  3. The sequence of the operations in terms of wrapping the layers starts with the top (layer 7: App.) All to often, I hear people say they are confused about the layers because layer one seems like it should be wrapped by the other layers. This mnemonic helps avoid that issue. Additionally, the layers read naturally from top to bottom when I see them represented, and this order makes writing them down more natural.
  4. Finally, the phrase reminds me that these abstractions all rest on a physical communication layer (i.e., when troubleshooting, start there first!)

If this helps you, great, and if not, I hope you find a mnemonic that works well for you 🙂

Finding Big M: Iteratively Estimating The Mean

Several months ago I wanted to estimate the mean of a value for users of an online app as quickly as possible with as few samples as possible. Every data point required scraping a webpage, and this proved timely AND costly in terms of system resources. Additionally, if I triggered too much traffic with my queries, the host would temporarily block the IP of my server.

Having theorized that the distribution was normal, I considered several more formal approaches (e.g., estimate power and then choose the appropriate sample size; sequential sampling; etc.) However, I was curious if I could develop an iterative approach that would both satisfy my precision requirements and help me get the data I needed as efficiently as possible given the cost of each web-scraping request.

Big M: A Generally Precise Estimate Of The Mean

While I didn’t need to publish the means I was estimating in scholastic journals, I wanted to ensure that the estimates were provably reliable in the general sense. That is to say, I wanted confidence intervals “in the nineties” or “in the eighties.” I wasn’t trying to disprove any formal null hypotheses, but I did want good data. I was training machine learning models for a class, and I wanted the most predictive models possible given my resource limitations.

I decided to play around with an iterative approach to generating a sample of large enough size to achieve the general degree of precision that I desired (even the thought of this would probably make my grad school stats professors throw up in their mouths.) This type of approach is a “no no” in statistics books, as you can generally grow a sample until you temporarily get what you want. You usually want to make informed a priori decisions about your research and then follow them to find your robust results.

However, I’d played around with Monte Carlo simulations a couple decades ago (I’m so old), and I always found it interesting how well various methods generally held up even in the face of violations of assumptions. Additionally, the ability of machine learning models to consistently converge on valid findings even in the face of crude hyperparamters has taught me to put things to the test before discounting them.

I set out to make a (relatively) simple algorithm for estimating the mean of the population to a general (e.g., “around ninety out of one hundred samples will contain the mean of the population with the given error constraint.”) I called this estimate Big M because, well, you know, D. Knuth is awesome, and Big O conveys a form of general precision that I wanted to embrace. If I’m working with big data, I don’t need a scientifically chosen set of samples that should guarantee a CI of 95%, I just need to know that I’m generally in the 90s.

The Big M Algorithm Overview

After trying out various forms of the algorithm, I developed the following approach, and a quick example Jupyter notebook is linked to containing code and several random results. Essentially, the code integrates the following algorithm.

  1. Select initial sample.
  2. Compute the confidence interval (CI) and mean.
  3. Check if the acceptable error (e.g., off by no more than 2 inches) is outside the confidence interval.
    1. If the acceptable error is outside the CI, increment the count of valid findings.
    2. If the acceptable error is inside the CI, start the count over at zero.
  4. Check if the continuous count has reached its threshold.
    1. If the continuous count has reached its threshold, exit the function with the mean estimate.
    2. If the continuous count has not reached its threshold, add one more observation to the sample and return to step 2.

There are some other details of note. The continuous count formulation is based on the ratio of the population size to the initial sample size and the confidence percentage chosen. Additionally, there is a maximum sample size that is formulated automatically by the size of the population and the initial sample size, though this parameter can be set manually.

The Big M Jupyter Notebook Example Code (Embedded as HTML)

I’ve linked to a demonstration of the code to implement the algorithm. Much of this is arbitrary, and I’m sure you could refactor this so it performs better. I’ve since developed a server-side implementation that’s quite different from this in a language other than Python, but this should (barring bugs, which obviously will be present) capture the general thrust of the algorithm and show general results (you can just rerun the Notebook to see new results.)

Big M Jupyter Notebook at GitHub


Monitor Network Traffic on an iOS Device Using Remote Virtual Interface

There are several situations in which one may want to monitor network traffic on an iOS device (e.g., ensuring there is no unexpected network traffic, identifying the APIs utilized by various apps, etc.) Let’s look at one possible option to accomplish this. From iOS 5 on, we can use Remote Virtual Interface (RVI) to add a network interface to your macOS device that contains the packet stream from an iOS device.

Install Xcode From The App Store

First, ensure that you’ve installed Xcode from the App Store on the Mac you’ll be using. It’s free, and it’s a straight-forward install.

Screen capture of search for Xcode
Find and install Xcode from the Apple Store.

Install Xcode Command Line Tools

Next, make sure you have the command line tools for Xcode installed on your system. You can type the following command to check if they are installed:

$ xcode-select --version
Screen capture of running command in terminal.
Ensure that the Xcode command line tools are installed.

If you don’t see any version information and you get a “command not found” type of error, you can use the following command to install the tools:

$ xcode-select --install

Of note, don’t try to use the same command above to update your installation of the command tools, just let Apple prompt you for an update (or, if you have automatic updates enabled, updates should happen without you needing to do anything.)

Connect Your iOS Device To Your Mac Computer

Then, connect your iOS device with your Mac computer using whatever wired connection is required (for my iPhone 8 and my iMac, I’m using a USB-to-Lightning cable.) Once connected, you just need to have both devices turned on so they can talk to each other (you may have to enter the passcode for your iOS device to unlock it.)

Start Xcode And Find Your UDID

Next, we have to locate the Unique Device Identifier (UDID) for your iOS device. The easiest way to do this (and have something you can copy into your command for the next step) is to use Xcode. After starting Xcode, you can navigate to the Window menu and then select Devices and Simulators. That will bring up a new window, then you can select the Devices tab, which should reveal detailed information about your iOS device. For our purposes, we need the value after the Identifier label (blurred out in my image below), which is the UDID for the device.

Screen capture of opening the devices tab in Xcode.

Find The “rvictl” Command On Your Mac

Now we need to open the terminal again. First, we have to find where the RVI command is located on your version of macOS. The find command can do this nicely, and we’ll enhance our command so we don’t see hundreds of permission denied messages.

$ find / -name "rvictl" 2>/dev/null

The output should reveal the location of the command. On my iMac running Catalina, the location is /Library/Apple/usr/bin, but make sure you check your system for the precise location.

Next, change to the directory of the rvictl binary and then run the command.

$ cd /Path/On/Your/System
Screen capture of running command in terminal.

Run The “rvictl” Command To Add Your iOS Device As A Network Interface

Finally, we can run the rvictl command and pass in the UDID we found earlier for our iOS device to start up a new network interface that will allow us to monitor the network traffic on the device using our Mac computer.

$ rvictl -s the-udid-number-of-your-ios-device
Screen capture of running command in terminal.

Test The Network Interface With tcpdump

Now that the network interface has been configured on your Mac for your iOS device (usually called rvi0), let’s test it to ensure that it’s working. Try using tcpdump to view HTTP activity on your iOS device and then visit a webpage on your phone that is using HTTP (not HTTPS.)

$ tcpdump -i rvi0 port http
Screen capture of running command in terminal.

Take Aways

You should now have the ability to configure your Mac computer to monitor network traffic on your iOS device. There are pros and cons to this particular approach. On the positive side, it is relatively easy if you’re using a Mac, unencrypted traffic is easily viewed, and the required applications/tools are few. However, if you you don’t own a Mac computer, or if you need to view encrypted traffic (e.g., HTTPS), there are better approaches. I’ll cover other monitoring options in the future that address these issues.

Xubri Educational Resources


One of my companies,, started a line of educational resources to help students finish good practice fast: Xubri. Now that the Xubri trademark has been registered, I’m going to start creating more educational resources under the Xubri name.

You might wonder why we waited for the trademark to be finalized before investing the time to create more resources. Well, I had a bad experience where I’d worked hard to build up the presence of an app in the Apple App Store. Then, someone created an app with the same name… except that they added “HD.” Seriously, they just called their app “name-of-my-app HD.” The similarly-name “HD” product seriously undermined my brand and advertising. Lesson learned!

So far, the brand includes several basic math facts apps in the Apple App Store and an audio single. However, there are several new apps being actively developed, and we’re really excited for what the future holds!