Wandering Thoughts archives


Wrangling HTTP and HTTPS versions of the same Apache virtual host

I recently tweeted:

It has been '0' days since I have been bitten by the fact that in Apache you usually have separate configurations for the HTTP and the HTTPS version of a site even if you want them the same, so you can change the wrong one when testing and be confused when a fix doesn't work.

(This was part of discovering how not to use RewriteRule in a reverse proxy.)

We have a bunch of named virtual hosts that we have set up for people; many although not all of them are reverse proxies to user run web servers. Increasingly people ask for (and we provide) both a HTTP and a HTTPS version of the site. The most natural and least complicated way to do this is to have a big Apache configuration file with all of our named vhosts and to repeat the configuration for a host between the HTTP and HTTPS versions.

This tends to look something like:

<VirtualHost 128.100.X.XX:80>
  ServerName ahost.cs.<etc>

  [all of ahost's configuration]

<VirtualHost 128.100.X.XX:443>
  ServerName ahost.cs.<etc>
  SSLEngine on
  [TLS certificate settings]

  [all of ahost's configuration]

When you do this and you have some RewriteRule settings or something complex that you're trying to fix, it's possible to accidentally change the HTTPS version of the site but not the HTTP version and then test against the HTTP version. Or vice versa. This is made easier when the site's configuration is big enough to push the other version of the site off your editor screen.

One answer is that we're shooting both ourselves and other people in the foot by even having a meaningful HTTP site here. If people ask for a HTTPS site, we should default to making their HTTP site redirect everything to the HTTPS one (and probably the HTTPS one should set a HSTS header). This would make the mistake impossible to commit, because the only site with real configuration would be the HTTPS one.

Failing that, what I would like is some way to have the same block apply to both the HTTP and HTTPS virtual host. In my imagination, it would look something like:

<VirtualHost 128.100.X.XX:80 128.100.X.XX:443>
  ServerName ahost.cs.<etc>

  <IfPort :443>
    SSLEngine on
    [TLS certificate settings]

  [all of ahost's configuration]

(Apache 2.4 has an <If> directive, but my understanding is that it takes effect too late to do this.)

One possible answer is to put the vhost's real configuration in a separate file that is Include'd in both. Unfortunately I don't think this scales for us; we don't like splitting things up this way in general, and we have enough virtual hosts where the HTTP and HTTPS versions are different that they would be exceptions in this scheme in one way or another. We'd prefer to keep everything in one file where it's at least readily visible all at once.

Another possible answer is mod_macro (first brought to my attention by @ch2500). Unfortunately as far as I can see this involves adding an extra configuration block for each such virtual host (for the <Macro> definition), and makes the actual HTTP and HTTPS <VirtualHost> blocks more magical and harder to read. I'm not all that enthused and my co-workers would almost certainly reject this as too much magic even if I proposed it.

(Some but not all of our virtual hosts could be done with a common <Macro> template, but that would create even more magic.)

web/ApacheVhostHTTPAndHTTPS written at 23:24:38; Add Comment

What OpenSSH sshd logs when a session disconnects (on Linux)

On Twitter, I recently was disgruntled about sshd's logging:

I really wish sshd logged one single line that said a session had ended, what user it was for (and where from), and what the reason for ending the session was. You might think it already did this, but sadly not.

There are many reasons you might care about the causes of SSH session disconnections, including that you're trying to troubleshoot potential network or firewall problems and you want to see if people are getting abruptly disconnected from their SSH sessions or if the sessions are ending normally.

For many sessions, sshd will log something like:

sshd[32625]: Received disconnect from port 51726:11: disconnected by user
sshd[32625]: Disconnected from user ckstst port 51726
sshd[32569]: pam_unix(sshd:session): session closed for user ckstst

(You can also see 'disconnected by server request'.)

This is already less than ideal, because the user is mentioned on a different line than the nominal disconnection reason. In addition, the PID logged for the first two messages appears from nowhere; it's not in any other log lines for the session, which are found for the PID in the third line.

However, a suspicious system administrator might see the message about 'disconnected by user' and wonder what happens when the user's TCP connection just gets cut for some reason, such as their machine shutting down abruptly. At least some of the time, what you get is more obscure:

sshd[14867]: Timeout, client not responding
sshd[14719]: pam_unix(sshd:session): session closed for user ckstst

The second PID logged, PID 14719 here, is associated with other earlier log lines that give you the remote IP. The first PID, PID 14867, has never been seen before or since (apart from PID rollover).

However, sshd can log even less. Suppose that something either abruptly terminates the user's SSH client program or causes TCP resets (RSTs) to be generated for the TCP connection. Then you will get only the log line:

sshd[9857]: pam_unix(sshd:session): session closed for user ckstst

One reason that TCP resets might be generated is state table entries timing out on some firewall between your server and the person logging in. Many home routers are also NAT firewalls and often have small state tables and aggressively time out entries in them.

All of this lack of clear logging forces forces you into reasoning by omission. If there is a 'Received disconnect' and a 'Disconnected' message logged by sshd, the session was disconnected in an orderly way and you can get the reason from the specific trailer. Even here in the best case you need to correlate three log lines to recover all information about the session. If there's no messages about the session ending from sshd but there is a 'Timeout' or other logged sshd error immediately before the PAM message, the TCP connection was most likely lost. Finally, if there's nothing other than the PAM message the session probably ended because of some abrupt termination of the TCP connection (either by client death causing the TCP connection to be closed or by firewalls deciding to reset it).

The one bright spot in all of this is that you always get the PAM message (as far as I know) and it always has the login name.

linux/OpenSSHDisconnectLogging written at 00:46:29; Add Comment

Page tools: See As Normal.
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.