How to use Linux and Iptables to route and masquerade ipv4 network traffic

You can use the shell script below to route and masquerade traffic coming to a network interface (“in_nic” variable) to another one (“out_nic” variable):

#!/bin/sh

set -e
set -u

in_nic=eth0
out_nic=eth1

# Flush old iptables rules
iptables -F; iptables -X
iptables -t nat -F; iptables -t nat -X
iptables -t mangle -F; iptables -t mangle -X

# Iptables policies (accept OUTPUT only)
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Route and masquerade traffic 
iptables -A FORWARD -i "$in_nic" -o "$out_nic" -j ACCEPT
iptables -A FORWARD -i "$out_nic" -o "$in_nic" -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t nat -A POSTROUTING -o "$out_nic" -j MASQUERADE

(the script is also available on gist: iptables-route-masquerade-traffic.sh)

Python script to clone all Git repositories from your GitHub account

Clone the repository Asher256/github-cloneall, install pip dependencies and copy the configuration file to your home directory:

$ git clone https://github.com/Asher256/github-cloneall
$ cd github-cloneall
$ pip install --user -r requirements.txt
$ cp github-cloneall.yml ~/github-cloneall.yml

Add your GitHub credentials to ~/github-cloneall.yml:

$ vim ~/github-cloneall.yml

Run github-cloneall to clone all Git repositories from your GitHub account to a local directory:

$ ./github-cloneall.py

(the script will also add “git remote add upstream <URI>” to the Git repositories that were forked)

Puppet module to configure LizardFS (Distributed File System) on Linux

I recently developed the Puppet module Asher256/puppet-lizardfs that can help you configure LizardFS, a highly-available distributed file system (DFS).

The Puppet module Asher256/puppet-lizardfs is an open source project. Community contributions are essential for keeping it great. I encourage you to contribute to the project. Send me your pull requests on Github! Currently, puppet-lizardfs supports the operating systems Debian/Ubuntu and RedHat/CentOS.

Continue reading

3 advices to write robust Bash scripts

To write robust Bash scripts, I recommend you to:

1. Activate the Bash options: errexit, nounset

Add these two options at the top of your Bash scripts:

#!/usr/bin/env bash
set -o errexit      
set -o nounset
  • errexit will stop your Bash script each time a command in your script returns an exit code different from “0”. It does not show any message when it quits, this is why it is important to show a traceback (check the second advice below “show a Bash traceback”).
  • nounset will stop your script and output an error if you attempt to use undefined variables. nounset is very important because it can avoid you to run dangerous commands like: rm –fr “/$undefinedvariable”

2. Show a Bash traceback

In some cases, the option “set -o errexit” doesn’t show any message when it stops your Bash scripts (e.g. var=$(your_failed_command) will exit silently). I recommend you to add the source code below at the top of your Bash scripts to make them show a traceback each time “errexit” stops your script:

#!/usr/bin/env bash

set -o errexit    # stop the script each time a command fails
set -o nounset    # stop if you attempt to use an undef variable

function bash_traceback() {
  local lasterr="$?"
  set +o xtrace
  local code="-1"
  local bash_command=${BASH_COMMAND}
  echo "Error in ${BASH_SOURCE[1]}:${BASH_LINENO[0]} ('$bash_command' exited with status $lasterr)"
  if [ ${#FUNCNAME[@]} -gt 2 ]; then
    # Print out the stack trace described by $function_stack
    echo "Traceback of ${BASH_SOURCE[1]} (most recent call last):"
    for ((i=0; i < ${#FUNCNAME[@]} - 1; i++)); do
    local funcname="${FUNCNAME[$i]}"
    [ "$i" -eq "0" ] && funcname=$bash_command
    echo -e "  $i: ${BASH_SOURCE[$i+1]}:${BASH_LINENO[$i]}\t$funcname"
    done
  fi
  echo "Exiting with status ${code}"
  exit "${code}"
}

# provide an error handler whenever a command exits nonzero
trap 'bash_traceback' ERR

# propagate ERR trap handler functions, expansions and subshells
set -o errtrace

The traceback will help you to know which command in your Bash script failed with a return code different from “0”:

Error in ./test.sh:43 ('false' exited with status 1)
Traceback of ./test.sh (most recent call last):
  0: ./test.sh:43	false
  1: ./test.sh:49	main
Exiting with status -1

3. Check your Bash scripts with shellcheck and follow the recommendations of Advanced Bash-Scripting Guide.

Temporarily prevent Linux from shutting down

Accidental shutdown or reboot is a serious blunder, especially if the kernel is being updated in the background.

I recommend you to use systemd-inhibit to prevent Linux from shutting down while your important cron jobs are running (e.g. operating system update scripts):

systemd-inhibit --why="Doing update" ./my-update-script.sh

systemd-inhibit will block the shutdown or reboot until the update script is finished.

Additional options:

  • –who=”your name”
    A human-readable name
  • list
    List all active inhibition locks

How to stop and remove all docker images and containers

Docker is a great tool, but it can sometimes consume a lot of disk space. Docker-clean is a simple bash script you can use to remove all docker images and containers:

$ git clone https://github.com/zzrotdesign/docker-clean
$ cd docker-clean
$ ./docker-clean --help
Options:
-h or --help        Opens this help menu
-v or --version     Prints the current docker-clean version

-a or --all         Stops and removes all Containers, Images, and Restarts docker
-c or --containers  Stops and removes Stopped and Running Containers
-i or --images      Stops and removes all Containers and Images
-net or --networks  Removes all empty Networks
-s or --stop        Stops all running Containers

--dry-run           Adding this additional flag at the end will list items to be
                    removed without running the remove or stop commands

-l or --log         Adding this as an additional flag will list all
                    image, volume, and container deleting output

To stop and remove all Docker containers:

$ ./docker-clean --containers

To remove all Docker images:

$ ./docker-clean --images