[Top] [All Lists]

Re: Abort data transfer?

2009-10-20 08:26:37

On 20 Oct 2009, at 02:20, David MacQuigg wrote:
Arnt Gulbrandsen wrote (about letting the transmitter hang):
Some people do this in order to be as occupy the sender's resources. There's a fancy name for it. You send one byte every few minutes, so it takes three hours to send the whole SMTP response. I don't know whether doing so really inconveniences the $#(_at_)$#@! spammers and other evil creatures who initiate most SMTP connections.

I wasn't thinking of a tarpit. That would involve keeping a connection on my end. Just dropping the connection will leave the transmitter with an SMTP process filling memory for maybe ten minutes.

Really? I rather fancy it will inform the sender's TCP that you're done with it, and the next few failed sends will go completely unnoticed by ratware and actioned upon by connection closure by a real MTA on a failed send or on an error detected on read by some more fancy event-driven process. In any case the length of the long wait is one TCP buffer, or not very long at all except perhaps for sneakernet. :-)

Perhaps you mean something more complex, maybe losing TCP state completely at your end. That might make a few long-suffering implementations wait a good while to give up. But if you were going to go that far, you might as well turn a real BOFH, advertise an MSS of 1 to evil clients, drop every packet except the fifteenth a turn, and delay each acknowledgement by five minutes. >:->

SM wrote:
Section of RFC 5321 discusses about the maximum total length of a message content. There isn't a permissible way within SMTP to abort during DATA. It's a "don't do it unless you know what you are doing".

I see no technical problem on the server side with sending "552 Too much mail data," then a TCP reset. If the client keeps retrying, without fixing the problem, I would block that IP address for a few hours.

It should work, but you can't depend on it. It would work with my client since all errors are detected during reads and not writes. But you simply can't depend on a client maintaining state the way you hope it should. If sends fail because you've reset the connection, you may simply cause the sender to abort the attempt and retry. It's that simple.

Sabahattin Gucukoglu wrote:
My implementations note the reason for rejection, then switch the event handler for the connection to one that just reads each buffer and then throws it away. There is nothing more that can be done.

This could leave your receiver tied up for as long as the client keeps spewing garbage.

Correct. SMTP is not "Broken", as some people would have it, but it's a cruel world out there. Be prepared for the worst.

Though I don't say you should not try to defend against DoS attacks, realistically any malicious person already has numerous ways to attack available services no matter how you protect them. For SMTP, rate limit, connection limit per IP, etc are about the best you can hope for. A session timeout may also be plausible, though I didn't implement one in the server, only RFC-specified inactivity timeouts and am only half-convinced of a need to put it into the client.

Even trying to inform the sender by writing the error to it while it is sending won't necessarily work, because it might not choose to look at its inbuffers until it's quite finished spewing. And in any case that's standards violation territory you're wandering into.

Which standard? The paragraph above from Section 3.3. of 5321 seems to be talking about after the 354 reply is issued (past tense). I assume that means any time after that, not necessarily waiting for the end of data.

Nothing in RFC 5321, as far as I know and understand it, allows you to circumvent the lock-step nature of SMTP. That section seems to corroborate that. The best you can do is suddenly become unavailable, with apologies to the client. I suppose you can interpret the text to mean that closing the connection for other reasons is acceptable but as has already been explained by others this isn't called for for any case other than resource unavailability and will, quite reasonably, give you client retries.

So you'll just have to do what you can to keep the connection alive for the data to come in, then reject it and hopefully at that point you can resume the dialogue to finish up and ensure the sender will leave you alone. Anything else is basically suboptimal.

If we have a broken or malicious sender, it seems that the optimal solution would be one with the least resources on the server side. That would be not even keeping the connection alive.

That works only if you don't want retries. So it's suboptimal. Maybe, as has been said before, we've simply never been bothered enough about it to put it right, and make it more optimal. But right now, accepting data is basically mandatory, except when it isn't, which is to say, at the beginning of the response to the DATA command or after the final dot, and not inbetween.


<Prev in Thread] Current Thread [Next in Thread>