2009-05-24
An interesting bit of ssh and sshd behavior
We have a ssh keypair that's used to let an automated script have very
limited access to a remote system. As usual, we set up a whole host
of restrictions in the target account's authorized_keys
; we force
a specific command, we only accept the key from the host we expect it
from, and we specify the whole raft of no-* options, including no-pty
.
The command that gets forced for this particular keypair reads various
things that it needs from standard input (ie, the script).
Recently, we wound up doing plain 'ssh login@host
' as part of trying
to debug a problem. My expectation was that this would behave just like
the normal 'ssh login@host nominal-command
' (since the command was
being forced on the remote end anyways). Instead, what happened was that
the connection stalled, (apparently) doing nothing; you would type at it
and nothing happened. In fact, nothing even appeared (your typing wasn't
echoed).
What turned out to be happening is this: ssh doesn't notice if the
remote end refuses to create a pty. Instead it carries on exactly as
if it was talking to a pty, so it puts the local terminal into raw mode
and then sends your untranslated input to the other end (character by
character). And plain 'ssh login@host
' tries to do a login session,
which asks for a pty, while the remote end refused to set up a pty
and forced the command (instead of running any sort of shell).
When this happens, you get no visible output from your typing because
ssh leaves it up to the remote end to do that in pty mode. Also, you
generally get no visible reaction to what you've entered because when
you hit 'return', ssh sent the raw return (as a \r
), instead of the
cooked newline (\n
) that the other end is looking for. So in our
case, the remote command thought that we were just typing a really,
really long single line of input that we hadn't finished yet.
(Trivia: if you ever want to see if this is happening to you, type a
Control-J; this sends \n
directly. This is also useful to know if
your terminal winds up in raw mode because a program crashed.)
What modern email is good for
Suppose that you are creating a service today. What can you reasonably and sensibly use email for, given modern email principles?
My answer is that the only real use of email today is as a notification system: you send your users email to tell them that there is something waiting for them on your site (whether that is a message, a state change, or whatever). This is a bit extreme, but I think it's the necessary end result of the limits.
Since modern email is not reliable, you can't make email the only that you tell users about something; the chance that it will get rejected, dropped, or filtered is just too great. (And when this happens, it will not be the fault of your users for not carefully making sure that your email bypasses all filtering.)
So you need to give users a way to get at this information, such as through your website. Since you don't want to train your users to trust email, you don't want to send full copies of information by email; instead you want users to read it off your site using some captive communication system (one that is not susceptible to various sorts of spoofing attacks).
This winds up with the conclusion of 'email as notification system'. You keep the real information inside your system, and only use email to let users know about the existence of new messages et al. If a user's email system drops some messages, there's no big loss; the user will find out about these new things the next time they wind up on your website itself.
(It may be useful to aggregate these notification emails, so that the user is not barraged with a storm of them.)