I have some server applications and from time to time I'm being victim of some attacks which might be of interest and I'm going to describe in the following.

The most recent attack originated from (China). The IP address was the last server log and my (C) accept function was "broken" after it. The server was still running but no more connection could be established. It was not the first time I was attacked in this fashion, so I put some sniffer to investigate IP/TCP headers once a dubious source ip address from that area of china appeared. I noticed many SYN and SYN/ACK from that same source (most likely timed), but also, in roughly the same frequency, many SYN and SYN/ACK from completely different (to me random) sources.

I investigated further by simply googling them and found https://www.abuseipdb.com/check/, where many have reported them as doing port scans. I concluded two and a half things from this report and my sniffer results. (1) They are not flooding me on porpuse. At least I can't imagine they flood random people (which might be a lot) on porpuse. (2) They are using me to make these port scans, right? The SYN SYN/ACK sequences are looking to me just like some Idle scans (e.g. described here https://nmap.org/book/idlescan.html) and I am the "zombie"; and (2 & 1/2) That I cannot be used as a "zombie", because this IP header ID trick (described in the reference above) is not working anymore on newer operating systems and I am using ubuntu server (kept up to date).

So are there some newer variants of the Idle scan than this one variant described in reference above, which also work on the most recent ubuntu server releases?

Did somebody experience in the same way I'm experiencing and knows what exactly he is doing and how to protect against it? To sum up the pattern its (a) exactly one clean server log after making the TCP handshake; and (b) many SYN and SYN/ACK from this attacker and other sources.

I appreciate any help and will provide any additional logs, etc... if needed.


I'm trying to sum up the most relevant part of my server code in the following.

So I'm first creating the server socket, then binding, listening and setting it to non-blocking.

fd_t sockfd_80; //wrapper for socket; calls socket(AF_INET,SOCK_STREAM | SOCK_CLOEXEC,IPPROTO_IP) in constructor; calls close(...) in destructor
sockfd_80.reuseaddr(); //sets SO_REUSEADDR
sockaddr_in const addr_80{AF_INET,htons(80),inet_addr(""),{}};
assert(bind((int)sockfd_80,reinterpret_cast<sockaddr const*>(&addr_80),sizeof(addr_80)) != -1); //sockfd - bind
assert(listen((int)sockfd_80,128) != -1); //sockfd - listen
sockfd_80.setNonBlocking(); //sets O_NONBLOCK

Then the thread looping over accept is started

std::thread acceptThread([&]{ while(!finalize) accept_task(...);});

,where finalize is set to true on SIGINT. And accept_task looks like

void accept_task(...)

    sockaddr_storage addr;
    socklen_t addr_size = sizeof(addr);
    int fd = -1;

    fd = accept4((int)sockfd_80,reinterpret_cast<sockaddr *>(&addr),&addr_size,0);
    if(fd == -1){
        if((errno != EWOULDBLOCK) && (errno != EAGAIN)){
            std::string errMsg(1024,0);
            ERR << strerror_r(errno,errMsg.data(),errMsg.size()) << std::endl;
        errno = 0;
      //do some analysis
      //close the socket
      //make a server log
      //do some additional stuff if needed (e.g. some openssl etc.)
      //add to epoll where events =  EPOLLHUP | EPOLLERR | EPOLLRDHUP | EPOLLIN | EPOLLONESHOT

UPDATE: Happened today again from Does anybody have a server log from this ip and can give me a bit more information what he is doing and how to prevent him from doing whatever he does? I'm really desperate by now, it's pretty impossible to debug because the event is so rare (once every two weeks).

  • I don't really understand how your accept function got broken by this. This looks to me more like a bug in the (unknown) server code, i.e. maybe a server which does not expect that accept can fail or which does accept after select or poll or similar and does not expect that accept can still block even if there were data on the listening socket. Sep 3 '19 at 5:03
  • @SteffenUllrich Hello and thank you for your comment. What I mean by saying accept is broken is that it always fails with errno ECONNABORTED and accept is called on a own single thread on a non-blocking socket. I really don't think it is a bug because this is happening approximately once every 2 weeks for almost a year now always after a server log with an ip address from this area of china.
    – ezegoing
    Sep 3 '19 at 12:19
  • It is perfectly fine to accept return ECONNABORTED since connections are accepted in the kernel and it might already be closed/aborted once you call accept. Or are you saying that accept always fails with ECONNABORTED and that it will only recover once you've a) restarted the process or b) rebooted the machine or c) ???. Sep 3 '19 at 12:31
  • @SteffenUllrich Yes, accept starts to fail always with ECONNABORTED and it is enough to recover by just restarting the c/c++ server programm in that sense. Probably also by just "restarting" the server socket, I have not tested to recover by just going for another server socket filedescriptor. Well restarting the server socket might even solve my issue?
    – ezegoing
    Sep 3 '19 at 12:39
  • I find it very strange that the socket never recovers from ECONNABORTED but that a restart of the process helps. I rather suspect a coding problem here - but unfortunately I don't have the code you use for analysis. Sep 3 '19 at 14:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.