mIRC Home    About    Download    Register    News    Help

Print Thread
mIRC dislikes Windows TCP teardowns if... #237424 03/05/12 12:49 AM
Joined: Aug 2006
Posts: 167
P
pishposh Offline OP
Vogon poet
OP Offline
Vogon poet
P
Joined: Aug 2006
Posts: 167
Most IRC server daemons are designed to minimize resource overhead in every possible way, one of which is while deflecting rapid clone connection attacks (with the message "ERROR :Your host is trying to (re)connect too fast -- throttled"). In the case of such messages, the typical behavior of an IRCd is to spew the error string followed by immediately destroying the TCP connection without waiting to see if the client is simultaneously attempting to sending anything -- e.g. the USER/NICK/PASS commands.

But there seems to be something different between the way Windows and Linux destroy sockets. mIRC seems to like the way Linux does it in the aforementioned scenario, but it barfs when that scenario comes from a Windows-based IRCd.

Specifically, when dealing with a Linux host, you will always see the "ERROR: Your host is trying to (re)connect too fast -- throttled" message followed by a nice, clean "* Disconnected" from mIRC. But when dealing with the same thing from a Windows host, mIRC almost always fails to show the server's message, displaying instead the dreaded "* [10053] Software caused connection abort".

Here's an example featuring a Windows server host, and showing two separate telnet clients successfully seeing the message, but mIRC failing 7.5 out of 8 times:
http://img152.imageshack.us/img152/9743/toofast.png

(Please note: the telnet clients receive the string every time -- even though I'm not demonstrating more than 2 occurrences.)

The easiest way to reproduce this is to simply make mIRC (running under Windows) emulate such an IRCd message followed by its immediate TCP teardown:

Code:
alias portopen /socklisten localhost 12345

alias portclose /sockclose localhost

on *:SOCKLISTEN:localhost:{
  /sockaccept localhostx
  /sockwrite -n localhostx ERROR :Your host is trying to (re)connect too fast -- throttled.
}

on *:SOCKWRITE:localhostx:/sockclose localhostx

Put that in mIRC on a spare Windows machine elsewhere on your LAN, and type /portopen in it. Then back on your main machine, in mIRC, do /server lan.ip.address.here 12345 repeatedly, and you should witness mIRC frequently fail to show you the "server's" message.

A real Windows IRCd will cause the problem too, of course. If anyone wants to reproduce the issue with one, the fastest way I know how is:

a) Get the source code for BewareIRCd (a simple, free, open source Undernet IRCu clone that's portable and stand-alone -- no install/uninstall process): http://ircd.bircd.org/bewareircd-src.zip

b) Unpack it into a temporary directory.

c) In bsock.pas, change "if ipc = nil then begin" to "if ipc <> nil then begin" (http://i.imgur.com/TQ09t.png -- this just forces the daemon to answer with the throttled ERROR message)

d) Install (ugh) free pascal (it's quick to do -- just use all-default settings in the installer wizard): http://www.freepascal.org/download.var

e) Compile BewareIRCd by typing "[path_to_freepascal_executable]\fpc.exe -Mdelphi bircd.dpr" (ignore the many compiler warnings)

f) Execute bircd.exe

g) /server 127.0.0.1 6667 (as many times as you want to observe/packetsniff/etc the issue)

h) Execute "bircd signal stop" to kill the daemon when you're done, then delete its temporary directory, and finally: Start Menu > All Programs > Free Pascal > Uninstall Free Pascal

FWIW, you can do the same steps above, but on a Linux machine (free pascal is available for linux too, and the same source zip will compile under linux). If you do, you'll notice that the Linux bircd executable's connection terminations will not trouble mIRC at all; the message displays properly, followed by no [10053].

P.S. I wonder if mIRC's trouble with Windows connection teardowns might explain some percentage of the [10053] errors that are commonly suffered inexplicably by mIRC users. The basic issue, as near as I can tell, seems to be that mIRC reports [10053] when a Windows TCP/IP stack (server side) is doing the TCP teardown sequence at the same time mIRC is sending data to it.

Re: mIRC dislikes Windows TCP teardowns if... [Re: pishposh] #237425 03/05/12 01:55 AM
Joined: Oct 2003
Posts: 3,918
A
argv0 Offline
Hoopy frood
Offline
Hoopy frood
A
Joined: Oct 2003
Posts: 3,918
I too wouldn't be surprised that mIRC is doing *something* quirky that is causing the 10053's. Many people have had this theory before, but it's been ridiculously difficult to prove. If this bug post unearths the long standing problem, I think you might deserve some kind of prize.


- argv[0] on EFnet #mIRC
- "Life is a pointer to an integer without a cast"
Re: mIRC dislikes Windows TCP teardowns if... [Re: argv0] #237433 03/05/12 03:02 PM
Joined: Aug 2006
Posts: 167
P
pishposh Offline OP
Vogon poet
OP Offline
Vogon poet
P
Joined: Aug 2006
Posts: 167
Ugh, I knew I would forget something. After unpacking the source code zip, you also need to download the files from http://www.lcore.org/svnroot/lcore/trunk/ into the unpacked source code's directory: Then bircd will compile. smile (Sorry.)


Anyway:

argv0, I actually had a long diagnostics discussion with bircd's author last year about this, and had planned to report the issue here. But other priorities came up and I eventually forgot about it. In any case, I can pass along a few notes from our e-mails.

For one thing, timing seems to be a factor in the issue. For example, while packet sniffing, I noticed that the troublesome disconnects were occurring as follows (note: this happened entirely within my LAN, from mIRC under Windows to bircd on another Windows machine):

Code:
  me: syn
serv: syn ack
  me: ack
serv: psh ack "ERROR: Your host is trying to (re)connect too fast -- throttled" + 0d0a
  me: psh ack "CAP LS" + 0a
serv: fin ack
  me: psh ack "PASS myservpass" + 0a + "NICK mynick" + 0a + "USER myident 0 * :myname" + 0a
serv: rst

*************** Meanwhile, in mIRC:

* Connecting to 192.168.1.3 (6667)
-
* [10053] Software caused connection abort
-
* Disconnected

On a hunch, I decided to see what would happen if I shortened mIRC's login sequence, by constructing an ON ^LOGON event to send the same data, but without the extra CAP LS packet. The result (same intra-LAN windows machines scenario):

Code:
  me: syn
serv: syn ack
  me: ack
serv: psh ack "ERROR: Your host is trying to (re)connect too fast -- throttled" + 0d0a
  me: psh ack "PASS myservpass" + 0a + "NICK mynick" + 0a + "USER myident 0 * :myname" + 0a
serv: fin ack
  me: ack
  me: fin ack
serv: ack

*************** Meanwhile, in mIRC:

* Connecting to 192.168.1.3 (6667)
-
ERROR Your host is trying to (re)connect too fast -- throttled
-
* Disconnected

Seeing this at first, (and momentarily forgetting that the TCP protocol is a bit more complicated than this), I thought the problem was simply that mIRC kept sending even after it saw that the server was initiating the FIN ACK/ACK/FIN ACK/ACK teardown sequence -- forcing the server to resort to RST (which I believe is proper when a client doesn't cooperate with the FIN ACK/ACK/FIN ACK/ACK handshake).

But then I decided to restore mIRC's default login sequence (by removing the ON ^LOGIN override), and to then have a friend on the other side of the world run bircd under Windows (same OS+bircd versions as mine) so I could see if something different would happen with the vastly longer roundtrip lag involved (versus the tight timings of my LAN). The result that time:

Code:
  me: syn
serv: syn ack
  me: ack
  me: psh ack "CAP LS" + 0a
serv: psh ack "ERROR: Your host is trying to (re)connect too fast -- throttled" + 0d0a
  me: psh ack "PASS myservpass" + 0a + "NICK mynick" + 0a + "USER myident 0 * :myname" + 0a
serv: fin ack
  me: ack
serv: rst ack
serv: rst
serv: rst

*************** Meanwhile, in mIRC:

* Connecting to 95.XXX.XXX.XXX (6667)
-
ERROR Your host is trying to (re)connect too fast -- throttled
-
* [10053] Software caused connection abort
-
* Disconnected

Which disproved my simple assumption. Because clearly here the same FIN ACK/ACK/FIN ACK/ACK handshake failure (fallback to RSTs) is occurring -- only now, time itself is re-arranged, with the server receiving mIRC's packets on a delay, and reacting to each one with successive RSTs.

I guess that's when I remembered that the handshake sequence falling back to RSTs is unavoidable in a lagged environment if one side is trying to close while the other is simultaneously trying to send.

Still, just for curiosity's sake, I then reinstated the same ON ^LOGIN override, and tried his Windows bircd server agian. Result:

Code:
  me: syn
serv: syn ack
  me: ack
  me: psh ack "PASS myservpass" + 0a + "NICK mynick" + 0a + "USER myident 0 * :myname" + 0a
serv: psh ack "ERROR: Your host is trying to (re)connect too fast -- throttled" + 0d0a
serv: fin ack
  me: ack
serv: rst ack
serv: rst

*************** Meanwhile, in mIRC:

* Connecting to 95.XXX.XXX.XXX (6667)
-
ERROR Your host is trying to (re)connect too fast -- throttled
-
* [10053] Software caused connection abort
-
* Disconnected

Yup. Same as before, just one less RST, corresponding with the one-fewer packet from mIRC.

Which left me knowing only two things:

* with a Windows server, mIRC wasn't showing [10053] if the timing was tight enough to allow a successful FIN ACK/ACK/FIN ACK/ACK handshake
* with a Windows server, mIRC was discarding (or never seeing) the server message ("ERROR") if the timing was tight and if a teardown resorted to RST

And so with all that in mind, here's how things change when dealing with a Linux host:

After having the friend with Windows run bircd, I had another friend with Linux (and also on the other side of the world) run bircd for me. Here were the results, first with my shortened login sequence, then with mIRC's normal long login sequence:

Code:
  me: syn
serv: syn ack
  me: ack
  me: psh ack "PASS myservpass" + 0a + "NICK mynick" + 0a + "USER myident 0 * :myname" + 0a
serv: psh ack "ERROR: Your host is trying to (re)connect too fast -- throttled" + 0d0a
serv: fin ack
  me: ack
serv: rst
  me: fin ack
serv: rst
serv: rst

*************** Meanwhile, in mIRC:

* Connecting to 84.XX.XX.XX (6667)
-
ERROR Your host is trying to (re)connect too fast -- throttled
-
* Disconnected
Code:
  me: syn
serv: syn ack
  me: ack
  me: psh ack "CAP LS" + 0a
serv: psh ack "ERROR: Your host is trying to (re)connect too fast -- throttled" + 0d0a
  me: psh ack "PASS myservpass" + 0a + "NICK mynick" + 0a + "USER myident 0 * :myname" + 0a
serv: fin ack
  me: ack
serv: rst
  me: fin ack
serv: rst
serv: rst
serv: rst

*************** Meanwhile, in mIRC:

* Connecting to 84.XX.XX.XX (6667)
-
ERROR Your host is trying to (re)connect too fast -- throttled
-
* Disconnected

Immediately noticed: as with the overseas Windows machine, the extra CAP LS packet generated an extra RST. But also, I noticed a difference: while the Windows machine sent its first RST packet with both the "RST" and "ACK" flags enabled, the Linux machine sent its first RST packet with only the "RST" flag enabled. And to the Linux machine, mIRC responded with a "FIN ACK"; while to the Windows machine, mIRC did not.

I then decided to try the same thing (short sequence, long built-in sequence) against an Undernet server on the other side of the world (IRCu + some linux flavor) (note: the PASS parameter was omitted this time):

Code:
  me: syn
serv: syn ack
  me: ack
  me: psh ack "NICK mynick" + 0a + "USER myident 0 * :myname" + 0a
serv: psh ack "ERROR: Your host is trying to (re)connect too fast -- throttled" + 0d0a
serv: fin ack
  me: ack
serv: rst
  me: fin ack
serv: rst
serv: rst

*************** Meanwhile, in mIRC:

* Connecting to manchester.uk.eu.undernet.org (6667)
-
ERROR Your host is trying to (re)connect too fast -- throttled
-
* Disconnected
Code:
  me: syn
serv: syn ack
  me: ack
  me: psh ack "CAP LS" + 0a
serv: psh ack "ERROR: Your host is trying to (re)connect too fast -- throttled" + 0d0a
  me: psh ack "NICK mynick" + 0a + "USER myident 0 * :myname" + 0a
serv: fin ack
  me: ack
serv: rst
  me: fin ack
serv: rst
serv: rst
serv: rst

*************** Meanwhile, in mIRC:

* Connecting to manchester.uk.eu.undernet.org (6667)
-
ERROR Your host is trying to (re)connect too fast -- throttled
-
* Disconnected

Result: same as with the friend's linux bircd -- no CAP LS packet resulted in one less RST from server; and server sends "RST" instead of "RST ACK"; and mIRC replies to initial "RST" with "FIN ACK" (as opposed to sending nothing in reply to Windows' initial "RST ACK").

Anyway, even with all this, it's still a simplified overview which at best can only provide clues. There is more to the TCP protocol than just which packet flags are enabled and the coincidental order of packet arrival. There are sequence and sequence-acknowledgement headers which play a roll, and so forth. And I don't have the patience or time repeat every one of the tests above while screen-capturing every one of their packets.

But ... I will do one comparison. If anybody fond of headaches wants to decipher all this crap, have a blast. laugh

_______________________________________________________________________________

Packet 01: http://i.imgur.com/QVf9z.png
Packet 02: http://i.imgur.com/Xzazw.png
Packet 03: http://i.imgur.com/mfQG8.png
Packet 04: http://i.imgur.com/DzB07.png
Packet 05: http://i.imgur.com/3YtEn.png
Packet 06: http://i.imgur.com/CKiWL.png
Packet 07: http://i.imgur.com/fIGzt.png
Packet 08: http://i.imgur.com/bRHtn.png
Packet 09: http://i.imgur.com/qx5Nf.png
Packet 10: http://i.imgur.com/OkvpZ.png
Packet 11: http://i.imgur.com/2jUl3.png
Packet 12: http://i.imgur.com/m6vrc.png
Packet 13: http://i.imgur.com/p5bo3.png

Code:
* Connecting to manchester.uk.eu.undernet.org (6667)
-
ERROR Your host is trying to (re)connect too fast -- throttled
-
* Disconnected

Packet 01: http://i.imgur.com/bL80E.png
Packet 02: http://i.imgur.com/bJ5GO.png
Packet 03: http://i.imgur.com/JW1Bb.png
Packet 04: http://i.imgur.com/VHLcG.png
Packet 05: http://i.imgur.com/k1oJL.png
Packet 06: http://i.imgur.com/6LsrI.png
Packet 07: http://i.imgur.com/sJTFN.png
Packet 08: http://i.imgur.com/5SyeH.png
Packet 09: http://i.imgur.com/gtwMp.png
Packet 10: http://i.imgur.com/CPKJS.png
Packet 11: http://i.imgur.com/h8vYE.png

Code:
* Connecting to 95.XXX.XXX.XXX (30050)
-
ERROR Your host is trying to (re)connect too fast -- throttled
-
* [10053] Software caused connection abort
-
* Disconnected

Backup of all the packet screen captures (with proper file names): http://depositfiles.com/files/kl3hu1sl9 (packets.zip, 1.87 MB)

Re: mIRC dislikes Windows TCP teardowns if... [Re: pishposh] #237474 07/05/12 02:40 PM
Joined: Dec 2002
Posts: 4,584
Khaled Offline
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 4,584
Thanks for the detailed bug report. I was able to reproduce this issue. It was due to the way Winsock asynchronous socket Windows messages were being processed. mIRC was sending the logon messages the moment it connected to the server, prior to checking if there was a message with a connection error, which would occur in cases where a server disconnected immediately. The 10053 error may or may not have appeared depending on the timing of socket events. I have made a change that may resolve this issue.

Re: mIRC dislikes Windows TCP teardowns if... [Re: Khaled] #237475 07/05/12 07:34 PM
Joined: Aug 2006
Posts: 167
P
pishposh Offline OP
Vogon poet
OP Offline
Vogon poet
P
Joined: Aug 2006
Posts: 167
If I understand you correctly, you're saying that mIRC will now do this:

1. Negotiate 3-way TCP setup handshake in full
2. Pause for a moment, to see if server initiates TCP teardown handshake (and if so, perform a sockread to get the ERROR message)
3. If no teardown witnessed within delay period, send login commands

If that is correct, then I do not believe it will solve the problem if:

1. Negotiate 3-way TCP setup handshake in full
2. Internet_lag >= your_delay postpones the arrival of server's PSK ACK "ERROR: throttled" packet + server's TCP teardown handshake packets

What apparently needs examination is why mIRC responds differently to Linux server teardowns vs. Windows server teardowns [when mIRC is simultaneously sending data to the server doing the teardown]. Right now, the bug doesn't occur at all if mIRC is dealing with a Linux server (regardless of the coincidental timing factors involved). If mIRC could be made to handle teardown handshakes from Windows servers as nicely as it handles teardown handshakes from Linux servers, the bug should "automatically" resolve, and possibly some other strange occurrences of [10053] would stop happening too.

Re: mIRC dislikes Windows TCP teardowns if... [Re: pishposh] #237478 07/05/12 07:58 PM
Joined: Dec 2002
Posts: 4,584
Khaled Offline
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 4,584
mIRC uses Winsock to process asynchronous socket messages - it has no idea about "teardown handshakes". The change I mentioned in my previous post involves changing the way mIRC checks Winsock messages when initially connecting to a server. This particular issue has nothing to do with the 10053 connection issue reported by users in the past.

Re: mIRC dislikes Windows TCP teardowns if... [Re: Khaled] #237481 07/05/12 09:21 PM
Joined: Aug 2006
Posts: 167
P
pishposh Offline OP
Vogon poet
OP Offline
Vogon poet
P
Joined: Aug 2006
Posts: 167
Fair enough. I thought mIRC had its own sockets library doing socket I/O of your own design. I was under that impression because other clients in my possession which themselves use winsock were not having the same problem under the same circumstances (as per my original screen capture at http://img152.imageshack.us/img152/9743/toofast.png).

So ... if winsock does not expose programs to teardown handshakes, does this mean some of the [10053] errors people receive elsewhere are essentially unfixable -- and that they are unfixable because of Microsoft stupidity?

See, my impression was that the 10053 was happening in the login sequence as a result of mIRC sending anything (not just login commands themselves -- but any commands) to a remote Windows server after that remote Windows server began a teardown handshake (which, due to internet lag, really means mIRC innocently sends its data before it sees the remote teardown packets locally arrive, but that the remote side thinks mIRC sent that data afterwards). But since you now say this all depends entirely on winsock, the issue instead appears to become this: local winsock spews 10053 if remote teardown sequence changes midway from FIN/FIN ACK/FIN/FIN ACK to Windows-style FIN/[...]/RST ACK sequence (but not if remote teardown sequence changes midway from a FIN/FIN ACK/FIN/FIN ACK to Linux-style FIN/[...]/RST sequence.)

If I am correct about that, then I'm wondering if the cause of other ambiguous [10053] errors is: a Windows server initiating a sudden TCP teardown sequence at exactly the same time as mIRC sends (a) a user /msg, or (b) a script-initiated server command, or (c) mIRC sends a PING (or replies to a server PING with a PONG), or (d) (insert something else sent here).

This is only a curiosity. If it's true, I wouldn't be surprised that Microsoft made winsock incompatible with other winsocks in this scenario -- but what would be surprising is that they made it compatible with other linsocks in said scenario. wink

Re: mIRC dislikes Windows TCP teardowns if... [Re: pishposh] #237483 07/05/12 10:44 PM
Joined: Dec 2002
Posts: 4,584
Khaled Offline
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 4,584
There are several ways of handling sockets eg. event-driven, message-driven, blocking, non-blocking, and so on. Depending on which method an application is using, it may display slightly different behaviour from other applications. mIRC uses the non-blocking message-driven method. After applying the fix I mentioned, I am still able to reproduce the 10053 issue occasionally, though not as much as before. Since mIRC is processing Windows socket messages in the order that they are sent by Winsock, this seems to indicate that the issue is due to timing ie. a combination of connection roundtrip time, threading delays, Windows messaging lag, etc. and that Winsock may send the socket messages in a different order depending on that.