Slow SSH to new CentOS servers

Recently when installing new servers I 'randomly' had an issue where SSH connections would lag out for 20-30 seconds on login then function fine once authenticated.

I noticed this issue on CentOS 5/6 servers, however it probably applies to anything running glibc 2.10+.

Now while there are a few reasons SSH might be doing this (most of which can be seen using verbose flags), it wasn't the usual suspects (GSSAPI etc).

The interesting part was, this wasn't happening on all servers (they are standard config wise thanks to puppet).

It turns out the UseDNS setting was failing, very slowly. Now a simple way to quickly solve the issue is to set UseDNS no in your sshd_config file.

This might be acceptable, depending on how much you have access restricted however there is an alternative.

It turns out there was a change in glibc that can be seen on the changelog here.

Under some circumstances (especially when firewalls are involved) DNS resolution will fail and glibc should fallback, close the socket and start again. It would seem this takes rather a long while when trying to SSH!

Thankfully there is a (recently documented) option that you can add to your resolv.conf file single-request-reopen. This forces glibc to enter fallback mode straight away and kills the delay.

An example of the 'patched' /etc/resolv.conf file

# This file is managed via Puppet

# Servers
nameserver 8.8.8.8
nameserver 8.8.4.4
nameserver 208.67.222.222
nameserver 208.67.220.220

# Options
options single-request-reopen

Now you might want to dig into your network stack a little more and make sure you can handle IPv6/dual stack properly but for now, problem solved!

KVIrc update breaks Irssi Proxy

I recently updated KVIrc on OS X from 3.2.0 to 4.2.0. The update appeared to complete successfully, however on trying to connect to my Irssi Proxy server nothing appeared to happen.

The output from the server console was something like below

This is the first connection in this IRC context: using the global server
setting
Attempting connection to myirssiproxy.local (RawrIRC) on port 8000
Looking up the server hostname (myirssiproxy.local)...
Server hostname resolved to 10.44.1.1
Contacting IRC server myirssiproxy.local (10.44.1.1) on port 8000
Connection established [myirssiproxy.local (10.44.1.1:8000)]
Local host address is 10.44.1.2

It turns out that in 4.2.0 the servers automatically had 'Switch to SSL/TLS by using the STARTTLS extension' enabled.

Unfortunately Irssi Proxy doesn't like STARTTLS, so while the logs show successful connections no data is transferred over the socket.

The simple solution to get things back up and running properly is to disable the option under each server.

To do this browse to 'Configure servers' under Settings, double click on the server under the network, tab over to Advanced and disable 'Switch to SSL/TLS by using the STARTTLS extension'.

If you have a large number of servers you can also directly edit the ini file under ~/.config/KVIrc/config/serverdb.kvc. In this file each network is a section and each server is numbered.

To disabled STARTTLS for the first server in network A, your config should look something like the below

[A]
0_EnabledSTARTTLS=false

This will usually have a number of other items, a full example is below

[FreeNode]
0_Port=8000
0_Hostname=myirssiproxy.local
0_Ip=10.44.1.1
0_Nick=MyNick
NServers=1
RealName=MyName
0_Pass=Mypass
0_AutoConnect=true
0_EnabledSTARTTLS=false
NickName=MyNick
0_Id=Server1
0_EnabledCAP=false
0_RealName=MyName
0_User=MyUser
UserName=Damian

This also makes it quite easy to generally manage servers in KVIrc, outside of wide scale settings changes.

Running a WSGI app via Gunicorn from Python

Anyone who's familiar with Gunicorn will know just how simple it is to get up and running; gunicorn myapp.wsgi.

For a little project I'm working on I wanted to take this up a level and run Gunicorn from a Python script, passing in any options as required and not relying on sys.argv.

Because of the way most the Gunicorn application classes are written they expect to be run from the console_scripts setup and have rather close integration.

Unfortunately this made getting to the point of running run.py and having Gunicorn start, rather harder than it needed to be.

For the purposes of this post my WSGI application is the example Flask app;

# myapp.wsgi
from flask import Flask

application = Flask(__name__)

@application.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    application.run()

Now, to get this running under Gunicorn we need to create a custom application

# myapp.mycustomapplication
from gunicorn.app.base import Application
from gunicorn import util

class MyCustomApplication(Application):
    '''
    Custom Gunicorn Application
    '''

    def __init__(self, options={}):
        '''__init__ method

        Load the base config and assign some core attributes.
        '''
        self.usage = None
        self.callable = None
        self.options = options
        self.do_load_config()

    def init(self, *args):
        '''init method

        Takes our custom options from self.options and creates a config
        dict which specifies custom settings.
        '''
        cfg = {}
        for k, v in self.options.items():
            if k.lower() in self.cfg.settings and v is not None:
                cfg[k.lower()] = v
        return cfg

    def load(self):
        '''load method

        Imports our application and returns it to be run.
        '''        
        return util.import_app("myapp.wsgi")

As far as I can tell the minimum methods you can define is 3;

  1. __init__ - This sets up our base attributes
  2. init - This is called to load option settings, we use self.options to set the cfg items.

  3. load - This loads the application so when wsgi() is called the app runs!

To run the application we just need to initialize the MyCustomApplication class, passing any options as required.

#!/usr/bin/env python
# myapp.run

from myapp.mycustomapplication import MyCustomApplication

if __name__ == "__main__":
    options = {
        'bind': 'localhost:8080',
    }

    MyCustomApplication(options).run()

In practice you'd probably load the options from a config file in your program.

Hopefully this should help you getting Gunicorn running smoothly in a more integrated manner :)

RADIUS authentication on a Dell PowerConnect M6220 switch

A while back I posted the 'how-to' on setting up HP switches for RADIUS authentication (here for GbE2c L2/L3 switches and here for ProCurve switches).

I also had to setup some Dell PowerConnect M6220 switches; these proved to be slightly more complicated than the HP's, but followed the Cisco style config.

First we need add a custom login and enable method

aaa authentication login "LineName" radius local
aaa authentication enable "LineName" none

These are used for connections over SSH - "LineName" can be anything, I tend to use the company name to keep things standard.

On the second line, you could also use radius local - this would require a password to enter enable mode. Personally I control the login mode from the RADIUS server and find having to enter a password to get to enable again a hassle.

Next we need to setup the RADIUS server

radius-server host auth serverIpHere
name "server1"
usage login
key "SecretKeyHere"
exit

Now we just need to configure the ssh line to use our aaa methods

login authentication LineName
enable authentication LineName

Once complete you should be able to login via ssh using your RADIUS details.

If you require access to the switch over http(s) you can also configure the HTTP server to authenticate against RADIUS

ip http authentication radius local
ip https authentication radius local

We include local on every method to ensure we don't get locked out the switch.

RADIUS authentication on a HP ProCurve switch

To configure a HP ProCurve switch for RADIUS authentication you need to use radius-server with the following syntax.

radius-server host serverIp key "SecretKeyHere"

Once this is setup you need to configure the switch to authenticate against the radius server.

aaa authentication login privilege-mode 
aaa authentication console login radius local 
aaa authentication console enable radius local 
aaa authentication telnet login radius local 
aaa authentication telnet enable radius local 
aaa authentication web login radius local 
aaa authentication ssh login radius local 
aaa authentication ssh enable radius local 

We include the local option so that in the event of the RADIUS server being down we can still authenticate.