Philip Hutchins

Head in the cloud...

Creating a Proxy Host on Linux No Additional Software

It is fairly easy to create a linux proxy host that proxies traffic from other hosts that don’t have direct access to the internet. This is a great and simple solution for keeping your backend workers off of the public internet to avoid attacks while at the same time allowing outbound traffic from them.

Here are the steps to configure this setup…

Worker

Configuring the worker that does not have direct access to the internet

DNS

  • Ensure that the host is using an externally resolvable IP address for DNS (this may not be needed in most cases) edit /etc/resolvconf/resolv.conf.d/base add…
1
2
nameserver 8.8.8.8
nameserver 8.8.4.4
  • Reload config files for DNS
1
$ sudo resolvconf -u

Networking

  • Change default gateway to IP address of proxy host
1
2
$ ip route del default
$ ip route add default via 192.168.3.1

Making the settings persist through a reboot

Default Route Changes

  • On Ubuntu you would edit your interfaces file, /etc/network/interfaces and update your private network interface block to include the following…
1
2
up ip route del default
up ip route add default via 192.168.3.1

… it would then look something like this …

1
2
3
4
5
6
auto eth2
iface eth2 inet static
  address 192.168.0.2
  netmask 255.255.255.0
  up ip route del default
  up ip route add default via [PROXY_IP_ADDRESS]

Proxy Host

Configuring the proxy host to allow the worker to proxy it’s traffic through it

Networking

  • add iptables rules to enable nat and forwarding with masquerade

You can add them via command line…

1
2
3
4
5
*nat
iptables -t nat -A POSTROUTING -o [PUBLIC_INTERFACE] -j MASQUERADE
*filter
iptables -A FORWARD -i [PUBLIC_INTERFACE] -o [PRIVATE_INTERFACE] -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i [PRIVATE_INTERFACE] -o [PUBLIC_INTERFACE] -j ACCEPT

The static config that this produces looks a little different than the commands used via command line to create it. You can use $ iptables-save > iptables.rules to dump your rules to a file called iptables.rules. You can then use this file to programatically load the rules upon boot.

OR

You can create an iptables file /etc/iptables.rules to load the rules from…

1
2
3
4
5
*nat
-A POSTROUTING -o [PUBLIC_INTERFACE] -j MASQUERADE
*filter
-A FORWARD -i [PUBLIC_INTERFACE] -o [PRIVATE_INTERFACE] -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i [PRIVATE_INTERFACE] -o [PUBLIC_INTERFACE] -j ACCEPT

…then use the following bash script to restore the rules (this will wipe any existing rules not existing in /etc/iptables.rules

1
2
3
#!/bin/sh
iptables-restore < /etc/iptables.rules
exit 0
  • Enable forwarding at the OS level in configs which will persist at reboot by editing /etc/sysctl.conf and uncommenting net.ipv4.ip_forward and setting it to 1
  • Enable forwarding at the OS level by running…
1
  echo 1 > /proc/sys/net/ipv4/ip_forward

To set up proxying of ssh connections through the proxy host to the backend workers do the following

  • add iptables rules to proxy the ssh traffic to the appropriate hosts (note that this goes under the nat table, do not add another nat line if one alraedy esists)
1
2
3
4
5
6
7
8
9
10
11
12
13
*nat
...
# Proxy SSH connections to badkend hosts
-A PREROUTING  -p tcp -m tcp -d [PROXY_HOST_PUBLIC_IP] --dport [EXT_SSH_PORT_1] -j DNAT --to-destination [BACKEND_WORKER_HOST_1_PRIV_NET_IP]:[BACKEND_WORKER_HOST_SSH_LISTEN_PORT]
-A PREROUTING  -p tcp -m tcp -d [PROXY_HOST_PUBLIC_IP] --dport [EXT_SSH_PORT_2] -j DNAT --to-destination [BACKEND_WORKER_HOST_2_PRIV_NET_IP]:[BACKEND_WORKER_HOST_SSH_LISTEN_PORT]
-A POSTROUTING -p tcp -m tcp -s [BACKEND_WORKER_HOST_1_PRIV_NET_IP] --sport [BACKEND_WORKER_HOST_SSH_LISTEN_PORT] -j SNAT --to-source [PROXY_HOST_PUBLIC_IP]
-A POSTROUTING -p tcp -m tcp -s [BACKEND_WORKER_HOST_2_PRIV_NET_IP] --sport [BACKEND_WORKER_HOST_SSH_LISTEN_PORT] -j SNAT --to-source [PROXY_HOST_PUBLIC_IP]
...
*filter
# Proxy SSH connections to backend hosts
-A FORWARD -m state -p tcp -i [PUBLIC_INTERFACE] -o [PRIVATE_INTERFACE] --state NEW,ESTABLISHED,RELATED -j ACCEPT
-A [PUBLIC_INTERFACE_NICKNAME] -p tcp -m tcp --dport [EXT_SSH_PORT_1] -j ACCEPT
-A [PUBLIC_INTERFACE_NICKNAME] -p tcp -m tcp --dport [EXT_SSH_PORT_2] -j ACCEPT
  • $PUBLIC_INTERFACE_NICKNAME – refers to -A INPUT -i eth2 -j privnet where the interface nickname would be privnet and eth2 would be the private interface

Making the IPTables changes persist through reboot

On Ubuntu add the following bash script named iptablesload to /etc/network/if-pre-up.d/ (this will wipe any existing rules not existing in /etc/iptables.rules)

1
2
3
#!/bin/sh
iptables-restore < /etc/iptables.rules
exit 0

Debugging SSH Connection Issues

Debugging SSH connection issues can be tricky and frustrating.

Common Issues & Causes

  • ssh_exchange_identification: Connection closed by remote host
    • SSHD key’s are corrupt
    • Connection to host does not complete due to network issue
    • The signature for the remote host in known_hosts is not correct
    • There is a problem with the SSH Daemon on the remote host

Debugging Steps

  1. Check hosts.deny and hosts.allow and ensure that you are not blocking the client, or allowing the client if necessary
  2. Check MaxStartups value in /etc/ssh/sshd_config, the default is 10 but something like 10:30:60 is a bit safer for ssh brute force attacks
  3. Run ssh in debug mode. ..+ This will help to expose problems with things like keys and auth types.
1
ssh my.host.com -VVV
  1. Watch logs on remote server (if possible)
  2. Run sshd on separate port with debug logging to console ..+ This is a very useful step. After you start the ssh daemon on the remote host (we use a different port so that we can troubleshoot while being remote). The high port number allows you to run the sshd process as a non root user.
1
/usr/sbin/sshd -p 2121 -D -d -e

Explanation

1
2
3
4
-p    Set the listening port.
-D    This option tells sshd to not detach and does not become a daemon. It allows for easy monitoring.
-d    Enable debug mode.
-e    Write logs to standard error instead of system log.

How to Easily and Quickly Clean Up Your Ubuntu /boot Partition

Cleanup /boot

After a few kernel upgrades, the /boot partition can fill up quickly if yours is 100M like mine. It’s quite painful to remove package by package to free up some space so that you can continue upgrading. Here’s a helpful oneliner to clean up all unused kernel packages…

1
for i in `dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d'`; do sudo apt-get -y purge $i; done

OSX Equivalent Linux/UNIX Commands

There are a few staple commands that we use as engineers to trobleshoot issues on Linux machines and servers. Some of these unfortunately do not translate directly to OSX’s underlying UNIX based system. Fortunately three are equivalent commands for most of them!

Networking

It is very handy to be able to determine what ports are listening on a box, or not. It’s also helpful to be able to determine which process and binary is using that port.

List open ports

Linux

1
2
3
4
5
6
7
8
$ netstat -antlp
(snippet of output)
tcp        0      0 10.210.149.179:37499    10.210.149.179:21041    TIME_WAIT   -
tcp        0      0 10.210.149.179:36687    10.210.149.179:21041    TIME_WAIT   -
tcp        0      0 10.210.149.179:37499    10.210.149.179:21041    TIME_WAIT   -
tcp6       0      0 :::14150                :::*                    LISTEN      14765/zabbix_agentd
tcp6       0      0 :::21030                :::*                    LISTEN      15751/bitcoind
tcp6       0      0 :::21031                :::*                    LISTEN      15751/bitcoind

OSX

1
2
3
4
5
6
7
8
9
$ lsof -i -P -n
(snippet of output)
Bitcoin-Q  5114 phutchins   57u  IPv4 0x769f1abf3f7392c3      0t0  TCP 10.0.0.13:59997->188.138.104.253:8333 (ESTABLISHED)
Bitcoin-Q  5114 phutchins   62u  IPv4 0x769f1abf24ef47a3      0t0  UDP *:*
Bitcoin-Q  5114 phutchins   63u  IPv4 0x769f1abf46995463      0t0  TCP 10.0.0.13:59354->185.53.131.187:8333 (ESTABLISHED)
node       5115 phutchins   15u  IPv4 0x769f1abf251ad853      0t0  TCP *:9000 (LISTEN)
node       5115 phutchins   16u  IPv4 0x769f1abf251ae123      0t0  TCP 127.0.0.1:52442->127.0.0.1:27017 (ESTABLISHED)
node       5115 phutchins   17u  IPv4 0x769f1abf2516f123      0t0  TCP 127.0.0.1:52443->127.0.0.1:27017 (ESTABLISHED)
node       5115 phutchins   18u  IPv4 0x769f1abf2509a2c3      0t0  TCP 127.0.0.1:52444->127.0.0.1:27017 (ESTABLISHED)

List routes

Linux

1
$ route -n

OSX

1
netstat -nr

Accept DNS Push on Linux From OpenVPN

DNS Push from OpenVPN

If you’ve set up an OpenVPN server for multiple OS tennants, you might have noticed that your OSX clients connect and receive their DNS setting from the server just fine. Your Linux clients however, if running resolvconf or openresolv may not work as easily. Luckily there is a simple and easy fix.

The Fix

In the clients OpenVPN config file add the following…

1
2
3
script-security 2
up /etc/openvpn/update-resolv-conf
down /etc/openvpn/update-resolv-conf

You can also add this on the server side configuration in the Custom Directives section.

Note however tho that if you put this on the server side, all of your clients will get this change and the file that we are referencing above may not exist on their machines which will cause problems.

Compare Commits/Tags/Branches on GitHub

GitHub previously had a feature in their GUI allowing you to compare two different commits, tags or branches. The shortcuts to this feature in the GUI have been removed for some reason but the ability to do this is still there.

This is the basic URL format for doing a compare

1
http://github.com/<USER>/<REPO>/compare/[<START>...]<END>

Options

Some of the available options for compare are undocumented. (append these changes to the end of the URL)

Ignore whitespace changes

1
?w=1

Tracking Down the Chef-Server Missing Dependency Bug

Bug Description

Currently there is a fairly agrivating bug in the free version of Opscode’s (now called Chef to make it even easier to find on google) chef-server. This bug is exposed when a dependency of one of your cookbooks depends on a cookbook who’s dependency is not met.

Symptoms

  • Chef-server starts consuming 100% CPU
  • Chef-server becomes unresponsive for periods of time or until erchef is restarted

What is causing this bug?

The way that I understand it is that the depsolver that existed in older versions of chef-server was removed and it was the piece that was keeping us from hanging upon unresolved dependencies.

Needs Clarification

  • Is the bug triggered for missign dependencies at any depth into the dependency chain, or only second level and below?
  • Is the bug triggered when the dependency cookbook exists on the server but the version constraing is not met, or only when the cookbook does not exist on the chef-server at all?

How to Track Down Missing Dependency

1
knife exec -E 'puts api.post("/environments/_default/cookbook_versions", "run_list" => ["base", "chefdm-ssl"])'

What is the fix and when will it be pushed to a stable release?

The fix is to add the depsolver that was used in the old chef-server back with some tweaks and testing. This has been committed to master but has not been added to a stable release yet. As of the writing of this article, the fix has yet to be released. It will not be released in any of the 11.0.X releases but is planned to be added in 11.1.0. Huge thanks to Ho-Sheng for shedding some light on this topic!

omnibus-chef-server

You can build chef-server from the repo that contains the fix from here. https://github.com/opscode/omnibus-chef-server/commit/06d37db491f0040621f844354b2599631fb62e6b

There is some more documentation on building nightlies here. http://docs.opscode.com/api_omnitruck.html

Links

The main bug report and discussion thread are here. https://tickets.opscode.com/browse/CHEF-3921

The main piece of code is located here. https://github.com/opscode/chef_objects/commit/a3133ced037d1e508ff18723ad9a6f2b94dea1ea

This is where it gets pulled into the erchef binary. https://github.com/opscode/erchef/commit/316a09c0657fab6ff4eb2b9222ab84336a5f039a

OpsWorks Stack Host Listing and SSH Gem

Making Life with OpsWorks Easier

Working in OpsWorks is has been a generally positive experience. There are a few things that I would like to see changed like the ability to position your own custom chef recipes before OpsWorks built in recipes. Also there was a bit of a sorespot when we decided to automate running a few rake tasks from jenkins on a particular host in a particular stack. To solve this issue, I’ve created a Ruby Gem that has a dual purpose. In its current form it allows you to easily list all of your stacks, see the nodes in that stack with their IP’s and also SSH directly to a host using its stack name and hsotname.

To give it a shot simply… gem install owssh

The gem in use…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
owssh describe qa
Getting data for Stack: qa
┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓
┃ Hostname             ┃       Public IP ┃      Private IP ┃ Type             ┃ Status   ┃
┣━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━┫
┃ redis2               ┃  10.123.123.123 ┃  10.100.100.100 ┃ redis            ┃ online   ┃
┣━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━┫
┃ rails-app3           ┃     50.30.20.10 ┃  10.100.100.100 ┃ rails-app        ┃ online   ┃
┣━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━┫
┃ db-master2           ┃   100.10.10.123 ┃  10.100.100.100 ┃ db-master        ┃ online   ┃
┣━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━┫
┃ resque1              ┃    12.12.123.12 ┃   10.10.100.100 ┃ resque           ┃ online   ┃
┣━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━┫
┃ rails-app4           ┃     12.12.12.12 ┃   10.10.100.100 ┃ rails-app        ┃ online   ┃
┣━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━┫
┃ resqueplus1          ┃             N/A ┃             N/A ┃ resqueplus       ┃ stopped  ┃
┗━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━┛

owssh qa rails-app
Opening SSH connection to first of type 'rails-app' which is 'rails-app3'...
 This instance is managed with AWS OpsWorks.

   ######  OpsWorks Summary  ######
   Operating System: Ubuntu 12.04.4 LTS
   OpsWorks Instance: rails-app3
   OpsWorks Instance ID: [removed]
   OpsWorks Layers: Rails App Server
   OpsWorks Stack: QA
   EC2 Region: us-east-1
   EC2 Availability Zone: us-east-1d
   EC2 Instance ID: [removed]
   Public IP: 123.123.123.123
   Private IP: 123.123.123.123

 Visit http://aws.amazon.com/opsworks for more information.
Last login: Thu May  1 16:48:52 2014 from my.awesome.computer
phutchins@rails-app3:~$

Gem & Documentation

The code lives here… [git@github.com:phutchins/owssh.git]

OwSSH Documentation

My Dot Files

dot-files GitHub Repository

After setting up my dot files on different computers, and accounts a million and a half times, I decided to try to make life a little bit more easy and automate a few things. I’ve created a GitHub repository that contains all of my dot files and added a script that semi intelligently links them for you. The .bash_profile (.bashrc on linux) and .vimrc are set up such that they install most of the dependencies for osx or linux on their own. My goal is to make these where I use the same dot files for all computers and OS’s and have them work the same, doing whatever smartness in the background so that I/you don’t have to think about it.

I’ll add more detail to what all they’re doing a little at a time as well as some of the things that I hope to do with them down the road. Please share your tips and tricks in your dotfiles as I’d love to encorporate as much awesomeness as possible!

The Repo

git@github.com:phutchins/dot-files.git

Auto Connect to Server and Join Channels in Irssi

irssi is a wonderful chat client. I’m closing it and reopening it all of the time so its nice when it automatically connects to the server that you want, identifies your nickname and joins your channels. Here is how to do it.

How to configure irssi to auto connect to a server

Add the server or servers that you want to connect to

/SERVER ADD -auto -network freenode irc.freenode.net 6667

Set and Identify nickname

If you want to automatically set and identify your nickname with nickserv you can do it like this…

/NETWORK ADD -autosendcmd "/^nick phutchins;/^msg nickserv identify mysecurepassword;wait 2000" freenode

Automatically join certain channels upon connection to a specific network

To join a channel

/CHANNEL ADD -auto #powerline freenode

To join a channel with a password

/CHANNEL ADD -auto #awesomesecretchannel freenode supersecurepass