Using the same certificate/key for OpenVPN

Tags

,

You can allow multiple connections to OpenVPN using the same key and certificate. This is enabled by adding duplicate-cn to your server.conf. According to the OpenVPN manual:

duplicate-cn: Allows multiple clients with the same common name to concurrently connect. In the absence of this option, OpenVPN will disconnect a client instance upon connection of a new client having the same common name.

It is NOT advisable to enable duplicate-cn, as it is mainly for testing purposes. For production use, each client should have its own certificate and key.

AWS Lambda

Tags

,

AWS Lambda allows you to run code without provisioning servers – serverless.  The code you run is called a Lambda function.  You only pay for the compute time used by the Lambda function ($0.00001667 for every GB-second used and $0.20/1M requests after 1M free requests).

You can trigger your function off of specific AWS resources, such as S3 bucket, DynamoDB table, Kinesis stream, or Amazon SNS notification.  AWS Lambda automatically scales based on the rate of incoming requests.  It uses compute resources across multiple AZs in each region, providing fault tolerance.

When a Lambda function is invoked, AWS Lambda launches a container based on the configuration settings you provided.  That container will exist for some time after the function is executed and may be reused later (or not).  There is 512M disk limit and 5 minute execution window for your Lambda function.  For more information, see Lambda introduction and limits.

You can bundle the Lambda function as follows:

  1. Create a directory containing your code and any requirements.
    $ mkdir lambda_dir && cd lambda_dir
    
    $ cat requirements
    boto3 >= 1.3.0
    requests
    
    $ cat my_code.py
    #!/usr/bin/env python
    import requests
    
    def lambda_handler(event, context):
        try:
            requests.get("http://www.google.com")
        except requests.exceptions.RequestException:
            print "Could not reach Google!"
    
    $ pip install -r requirements.txt -t .
  2. Zip the content of this directory (not the directory!).  Upload the zip file directly to AWS Lambda or to an S3 bucket (for zip files larger than 10M).
    $ zip -r ../lambda_bundle.zip *

Use my_code.lambda_handler as the Lambda handler. Any messages sent to stdout will be found in CloudWatch logs.

Apache Storm

Tags

Apache Storm is a distributed real-time computation system.

There are two types of nodes in a Storm cluster: master node and worker nodes.

  1. The master node runs a daemon called Nimbus. It is responsible for distributing code around the cluster, assigning tasks to machines, and monitoring for failures.
  2. Each worker node runs a daemon called the Supervisor.  It listens to work assigned to its machine and starts and stops work processes as necessary based on what Nimbus has assigned to it.
  3. All coordination between Nimbus and the Supervisors is done through a Zookeeper cluster.

Real-time computation is performed on Storm topologies.

  1. A topology is a graph of computation. Each node in a topology contains processing logic, and links between nodes indicate how data should be passed around between nodes.

The core abstraction in Storm is the stream.

  1. A stream is an unbounded sequence of tuples (i.e. a named list of values, where a field in a tuple can be an object of any type).
  2. Storm provides the primitives for transforming a stream into a new stream in a distributed and reliable way. For example, you may transform a stream of tweets into a stream of trending topics.

The basic primitives Storm provides for doing stream transformations are spouts and bolts.

  1. A spout is a source of streams. For example, a spout may connect to the Twitter API and emit a stream of tweets.
    1. A bolt consumes any number of input streams, does some processing, and possibly emits new streams.
    2. Complex stream transformations, like computing a stream of trending topics from a stream of tweets, require multiple steps and thus multiple bolts.
    3. Bolts can do anything from run functions, filter tuples, do streaming aggregations, do streaming joins, talk to databases, and more.
  2. Networks of spouts and bolts are packaged into a topology which is the top-level abstraction that you submit to Storm clusters for execution.

Reference:

  1. http://storm.apache.org/releases/current/Tutorial.html

Apache Kafka

Tags

Apache Kafka is a distributed streaming platform.  It can be used to stream real-time data (on topics) or transform real-time data.

  1. Kafka divides the data (called records) into categories called topics. Each record has a key, a value, and a timestamp.
  2. Kafka stores each record in a partition. Each partition is an ordered and immutable sequence of records that is continually appended to – a structured commit log.
    • The partitions are distributed across the Kafka cluster. Each partition is replicated across a configurable number of servers for fault tolerance.
    • Each partition has one server which acts as the leader and zero or more servers which act as followers. The leader handles all read and write requests for the partition while the followers passively replicate the leader.
    • Kafka only provides a total order over records within a partition, not between different partitions in a topic.
  3. Each record is assigned a sequential id number called the offset that uniquely identifies it.
    • The Kafka cluster retains all published records – whether or not they have been consumed – using a configurable retention period.

  4. Kafka is divided up into consumers and producers.
    • Consumers are grouped together. Each record published to a topic is delivered to one consumer instance within each subscribing consumer group. Consumer instances can be in separate processes or on separate machines.
    • Producers publish data to the topics of their choice. The producer is responsible for choosing which record to assign to which partition within the topic.

Reference:

  1. https://kafka.apache.org/intro

Paxos algorithm

Tags

,

Paxos is a consensus algorithm.  It is used to reach an agreement on a value among a number of nodes.

The (simplified) algorithm is as follows.

  1. A node is selected to be the leader (called proposer).
  2. The leader selects a value and sends it to other nodes (called acceptors) in a accept-request message.  Acceptors can reply with accept or reject.
  3. Once a majority of the nodes have accepted, consensus is reached. The coordinator broadcasts a commit message to all nodes.

More details:

  1. The leader selects a sequence number (x) and value (v) to create a proposal.
  2. An acceptor is going to reply agree if:
    1. It is the first proposal.
    2. If there are previous proposals, x is the highest sequence number proposal.
  3. If a majority of acceptors fail to reply or reply reject, the leader abandons the proposal and may start again.

References:

  1. https://www.quora.com/Distributed-Systems-What-is-a-simple-explanation-of-the-Paxos-algorithm
  2. http://lamport.azurewebsites.net/pubs/paxos-simple.pdf

 

DNS records

Tags

DNS servers translates domain names into IP addresses.  It allows you to use http://www.google.com instead of 63.117.14.21, which is not very easy to remember.  There are several types of DNS records.  They map the domain name to an IP address and tell the DNS servers how to handle your requests for that domain.

  1. A record: Most basic type of DNS record and used to point a domain or subdomain to an IP address.  Domain > IP address.
  2. CNAME record: Commonly used DNS entry and used to point a host/name to another host/name. Hostname > hostname.
  3. MX record: Specifies which server(s) to attempt to use to deliver mail to.
  4. TXT record: Used to store any text-based information that can be grabbed when necessary.
  5. NS record: Used to determine which servers will communicate DNS information for a domain.

Each record has a TTL associated with it. It determines the expiration (in seconds) of the record.

References:

Docker shortcuts

Tags

The following are useful shortcuts for Docker.

  • Build a container
    # cd /path/to/Dockerfile
    # docker build -t <image_name> .
    
  • Start a container (detached)
    # docker run -d <image_name> <args>
    
  • Enter a container with bash
    # docker exec -it <container_id> /bin/bash
    
  • Stop ALL containers
    # docker stop $(docker ps -a -q)
    
  • Delete ALL containers
    # docker rm $(docker ps -a -q)
    

Configuring OpenVPN

Tags

,

Background

VPN creates a secure and encrypted connection between your computer and the VPN server. It allows you to access your company’s private networks through this connection.  There are many VPN solutions available. OpenVPN is a popular open-source VPN solution available today.

OpenVPN was split into several sub-projects since version 2.3 – easy-rsa (PKI management) and openvpn (core project). easy-rsa is a set of scripts to build the root certificate authority (CA) and request and sign certificates. Most of the steps you need to take are documented here.

Setting up OpenVPN is straight-forward. Below are the steps to setup and configure OpenVPN.

OpenVPN Server

Install openvpn and easy-rsa.

# yum install easy-rsa -y --enablerepo=epel
# yum install openvpn -y

Copy the key and certificate generation scripts into /etc/openvpn.

# mkdir -p /etc/openvpn/easy-rsa && cp -rf /usr/share/easy-rsa/2.0/* /etc/openvpn/easy-rsa

Generate the server credentials.

# cat /etc/openvpn/easy-rsa/vars
# easy-rsa parameter settings

# NOTE: If you installed from an RPM,
# don't edit this file in place in
# /usr/share/openvpn/easy-rsa --
# instead, you should copy the whole
# easy-rsa directory to another location
# (such as /etc/openvpn) so that your
# edits will not be wiped out by a future
# OpenVPN package upgrade.

# This variable should point to
# the top level of the easy-rsa
# tree.
export EASY_RSA="`pwd`"

#
# This variable should point to
# the requested executables
#
export OPENSSL="openssl"
export PKCS11TOOL="pkcs11-tool"
export GREP="grep"
# This variable should point to
# the openssl.cnf file included
# with easy-rsa.
export KEY_CONFIG=`$EASY_RSA/whichopensslcnf $EASY_RSA`

# Edit this variable to point to
# your soon-to-be-created key
# directory.
#
# WARNING: clean-all will do
# a rm -rf on this directory
# so make sure you define
# it correctly!
export KEY_DIR="$EASY_RSA/keys"

# Issue rm -rf warning
echo NOTE: If you run ./clean-all, I will be doing a rm -rf on $KEY_DIR

# PKCS11 fixes
export PKCS11_MODULE_PATH="dummy"
export PKCS11_PIN="dummy"

# Increase this to 2048 if you
# are paranoid. This will slow
# down TLS negotiation performance
# as well as the one-time DH parms
# generation process.
export KEY_SIZE=2048

# In how many days should the root CA key expire?
export CA_EXPIRE=3650

# In how many days should certificates expire?
export KEY_EXPIRE=90

# These are the default values for fields
# which will be placed in the certificate.
# Don't leave any of these fields blank.
export KEY_COUNTRY="US"
export KEY_PROVINCE="Manhattan"
export KEY_CITY="New York City"
export KEY_ORG="Acme Corp"
export KEY_EMAIL="admin@acme.com"
export KEY_OU="IT"

# X509 Subject Field
export KEY_NAME="server"

# PKCS11 Smart Card
# export PKCS11_MODULE_PATH="/usr/lib/changeme.so"
# export PKCS11_PIN=1234

# If you'd like to sign all keys with the same Common Name, uncomment the KEY_CN export below
# You will also need to make sure your OpenVPN server config has the duplicate-cn option set
# export KEY_CN="CommonName"

Source the parameters to generate the server credentials. You will source these parameters again later to generate the client credentials.

$ source ./vars

Build the certificate authority (CA) certificate and key.

$ ./build-ca

Generate a certificate and private key for the server.

$ ./build-key-server server

When the Common Name is queried, enter “server”. Two other queries require confirmation, “Sign the certificate? [y/n]” and “1 out of 1 certificate requests certified, commit? [y/n]”.

Generate the Diffie Hellman key exchange for the OpenVPN server.

$ ./build-dh

Copy ca.crt, dh2048.pem, server.crt, and server.key into /etc/openvpn.

Create the server configuration file.

# cat > /etc/openvpn/server.conf << EOF
#################################################
# OpenVPN 2.0 config file for multi-client #
# server. #
#################################################

# Which TCP/UDP port should OpenVPN listen on?
port 1194

# TCP or UDP server?
proto tcp

# "dev tun" will create a routed IP tunnel
dev tun

# SSL/TLS root certificate (ca), certificate (cert), and private key (key).
# Each client and the server must have their own cert and key file. The
# server and all clients will use the same ca file.
ca ca.crt
cert server.crt
key server.key # This file should be kept secret

# Prevent any form of downgrade attack on the TLS protocol level by
# setting the minimum version.
tls-version-min 1.2

# Restrict the VPN control channel to strong cipher suites.
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384

# Change the VPN data channel to use AES with a 256 bit key in CBC mode.
cipher AES-256-CBC

# Diffie hellman parameters.
# Generate your own with:
# openssl dhparam -out dh2048.pem 2048
dh dh2048.pem

# Configure server mode and supply a VPN subnet for OpenVPN to draw client
# addresses from. The server will take 10.8.0.1 for itself, the rest will be
# made available to clients. Each client will be able to reach the server
# on 10.8.0.1.
server 10.8.0.0 255.255.255.0

# Maintain a record of client <-> virtual IP address associations in this
# file. If OpenVPN goes down or is restarted, reconnecting clients can be
# assigned the same virtual IP address from the pool that was previously
# assigned.
ifconfig-pool-persist ipp.txt

# If enabled, this directive will configure all clients to redirect their
# default network gateway through the VPN, causing all IP traffic such as
# web browsing and and DNS lookups to go through the VPN (The OpenVPN server
# machine may need to NAT or bridge the TUN/TAP interface to the internet
# in order for this to work properly).
# push "redirect-gateway def1"

# Certain Windows-specific network settings can be pushed to clients, such
# as DNS or WINS server addresses.
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

# The keepalive directive causes ping-like messages to be sent back and forth
# over the link so that each side knows when the other side has gone down.
# Ping every 10 seconds, assume that remote peer is down if no ping received
# during a 120 second time period.
keepalive 10 120

# Enable compression on the VPN link. If you enable it here, you must also
# enable it in the client config file.
comp-lzo

# It's a good idea to reduce the OpenVPN daemon's privileges after
# initialization.
user nobody
group nobody

# The persist options will try to avoid accessing certain resources on restart
# that may no longer be accessible because of the privilege downgrade.
persist-key
persist-tun

# Output a short status file showing current connections, truncated and
# rewritten every minute.
status openvpn-status.log

# Set the appropriate level of log file verbosity.
#
# 0 is silent, except for fatal errors
# 4 is reasonable for general usage
# 5 and 6 can help to debug connection problems
# 9 is extremely verbose
verb 4

# Set log file location.
log-append /var/log/openvpn.log

# Push routes to the client to allow it to reach other private subnets behind
# the server. Remember that these private subnets will also need to know to
# route the OpenVPN client address pool (10.8.0.0/255.255.255.0) back to the
# OpenVPN server.
push "route 192.168.0.0 255.255.255.0"
EOF

Remove the chance of our OpenSSL configuration not loading due to the version being undetectable. Do this by copying the required configuration file and removing the version number.

# cp /etc/openvpn/easy-rsa/openssl-1.0.0.cnf /etc/openvpn/easy-rsa/openssl.cnf

Verify dh2048.pem, ca.crt, server.crt, and server.key are on the OpenVPN server.

# chmod 600 /etc/openvpn/server.key

Add a rule to iptables to forward our routing to our OpenVPN subnet.

# iptables --flush
# iptables -A INPUT -i tun+ -j ACCEPT
# iptables -A FORWARD -i tun+ -j ACCEPT
# iptables -A FORWARD -i tun+ -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
# iptables -A FORWARD -i eth0 -o tun+ -m state --state RELATED,ESTABLISHED -j ACCEPT
# iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
# iptables -A OUTPUT -o tun+ -j ACCEPT
# iptables-save > /etc/sysconfig/iptables

Restart the network to enable the latest changes.

# service network restart

Start the openvpn service.

# service openvpn restart

OpenVPN Client

Each client needs there own key and certificate to authenticate with the OpenVPN server. Any OpenVPN client is supported. They are listed here. Below are the steps to create a client key and certificate for the user “tpham” (you need to change to a unique common name).

On the client machine (e.g. CentOS), install OpenVPN.

# yum install easy-rsa -y --enablerepo=epel
# yum install openvpn -y

Generate the client key and certificate. Source the parameters to use for easy-rsa (these are the same parameters as the server).

$ cd /etc/openvpn/easy-rsa
$ source ./vars

Generating client certificates.

$ ./build-key tpham

This will generate tpham.crt and tpham.key. Put these files under /etc/openvpn.

Create a client configuration file for openvpn to use, e.g. /etc/openvpn/tpham.conf.

cat > /etc/openvpn/tpham.conf << EOF
##############################################
# Client-side OpenVPN 2.0 config file #
# for connecting to multi-client server. #
##############################################

# Specify that we are a client and that we
# will be pulling certain config file directives
# from the server.
client

# Use the same setting as you are using on
# the server.
dev tun

# Are we connecting to a TCP or
# UDP server? Use the same setting as
# on the server.
proto tcp

# The hostname/IP and port of the server.
remote 192.168.0.1 1194

# Keep trying indefinitely to resolve the
# host name of the OpenVPN server.
resolv-retry infinite

# Most clients don't need to bind to
# a specific local port number.
nobind

# Try to preserve some state across restarts.
persist-key
persist-tun

# Enable compression on the VPN link.
# Don't enable this unless it is also
# enabled in the server config file.
comp-lzo

# Set log file verbosity.
verb 4

# Prevent any form of downgrade attack on the TLS protocol level by
# setting the minimum version.
tls-version-min 1.2

# Restrict the VPN control channel to strong cipher suites.
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384

# Change the VPN data channel to use AES with a 256 bit key in CBC mode.
cipher AES-256-CBC

# SSL/TLS parms.
ca $openvpn_directory/ca.crt
cert $openvpn_directory/guest.crt
key $openvpn_directory/guest.key
EOF

Restart OpenVPN to start the client.

$ service openvpn start

There are a few good articles on OpenVPN. Below are the ones used in this setup.

  1. https://community.openvpn.net/openvpn/wiki/Hardening
  2. https://www.digitalocean.com/community/tutorials/how-to-setup-and-configure-an-openvpn-server-on-centos-7

SSH tunneling

SSH tunneling (port forwarding) lets you connect from your local computer to another server.  Because the connection is encrypted, it is useful for transmitting information that uses an unencrypted protocol. [1]

$ ssh -AfL localport:host:hostport -N user@ssh_server

For example,

$ ssh -AfL 8500:192.168.1.2:8500 -N ec2-user@192.168.1.129

-A option enables forwarding of the authentication agent connection.
-f option requests SSH to go to background just before command execution.
-L option specifies local port forwarding.
-N option specifies do not execute a remote command.

For more details, see Port Forwarding [1].