user1688877
user1688877

Reputation: 41

SOCKET connection problems in a service on Windows Server 2012

I inherited a C++/Windows project where we have an SNMP extension agent (loaded by SNMP service). Inside the agent, we are creating a simple TCP server to which our client applications connect and provide it with data for SNMP queries/traps etc. This all seems to work fine on Windows Server 2008. However, on Windows Server 2012, the client can no longer connect to the server running inside the agent (in SNMP service). The connect() fails with error 10013.

My server code looks something like this:

fd_set  master_set;
fd_set  readfds;
SOCKET  listener;

WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
{
    OutputDebugStringA("WSAStartup failed\n");
    return -1;
}
FD_ZERO(&master_set);
FD_ZERO(&readfds);

//----------------------
// Create a SOCKET for listening for
// incoming connection requests.

listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listener == INVALID_SOCKET) {
    OutputDebugStringA("socket failed with error:\n");
    return -1;
}
int reuse_addr = 1;

setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse_addr, sizeof(reuse_addr));
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port for the socket that is being bound.
sockaddr_in service = { 0 };
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("127.0.0.1");
service.sin_port = htons(27015);

if (bind(listener, (SOCKADDR *)& service, sizeof(service)) == SOCKET_ERROR)
{
    printf("bind failed with error: %d \n", WSAGetLastError());
    closesocket(listener);
    return -1;
}

if (listen(listener, 5) == SOCKET_ERROR)
{
    OutputDebugStringA("listen failed with error\n");
    closesocket(listener);
    return -1;
}

u_long NonBlock = 1;
if (ioctlsocket(listener, FIONBIO, &NonBlock) == SOCKET_ERROR)
{
    OutputDebugStringA("ioctlsocket() failed with error\n");
    return -1;
}


FD_SET(listener, &master_set);

timeval timeout;
timeout.tv_sec = 3;
timeout.tv_usec = 0;

printf("Started Server on port %d\n", 27015);

for (;;)
{
    readfds = master_set;

int ret = select(0, &readfds, NULL, NULL, &timeout);

    if (ret == 0)
    {
        // Time out // Check if we need to shutdown

            continue;
    }
    
if (ret < 0)
    {
        printf("Error in Socket select\n");
        return -1;
    }

    for (int i = 0; i < readfds.fd_count; i++)
    {
        SOCKET xfd = readfds.fd_array[i];

        if (xfd == listener)
        {
            // New Connection.
            SOCKET new_fd = HandleNewConnection(listener);
            if (new_fd == -1)
            {
                printf("Error Accepting new connection");
                continue;
            }
            FD_SET(new_fd, &master_set);
            printf("Accepted new Connection\n");
            continue;
        }
        else
        {
            if (!HandleIncomingData(xfd))
            {
                closesocket(xfd);
                FD_CLR(xfd, &master_set);
                continue;
            }
        }
    }
}

SOCKET HandleNewConnection(SOCKET listener)
{
  SOCKET newfd = accept(listener, (sockaddr*)NULL, (int*)NULL);
  u_long NonBlock = 1;
  ioctlsocket(newfd, FIONBIO, &NonBlock);
  return newfd;
  }

  bool HandleIncomingData(SOCKET fd)
  {
  char buffer[16] = { 0 };
  int recv_bytes = -1;
  if ((recv_bytes = recv(fd, buffer, 16, 0)) <= 0)
  {
    printf("Connection Closed/ Error in Recieving");
    return false;
  }

  printf("recieved %d bytes\n", recv_bytes);
  return true;
}

The select continues to timeout every 3 seconds without any connection getting accepted.

Here's all that I have tried (none worked):

  1. Tried to run the service in a specific user account.
  2. The server is run in a separate thread, I provided a SECURITY_ATTRIBUTE with NULL DACL to see if it's a security problem.
  3. Tried different ports.
  4. Tried same server code in a separate normal application. The client can connect to this application.
  5. Sample server application when launched from the agent, the client cannot connect to it.
  6. Windows firewall is turned off and I don't have any anti virus software installed which would block such connections.
  7. Checked connection from outside and observed in Wireshark that the TCP SYN packet does arrive but there's no response to it.
  8. Observed in Process Explorer TCP/IP properties that the SNMP service does have a TCP socket listening on 127.0.0.1:27015.

For quick tests I am just doing telnet to port 27015.

  1. Is there something obviously wrong with the server code which I am missing?
  2. Is there some security restriction in Windows Server 2012 which don't allow a service to accept such TCP connections?
  3. Any other hints, comments, inputs?

Upvotes: 0

Views: 3510

Answers (2)

Fabian Pipolo
Fabian Pipolo

Reputation: 1

I could solve it following these steps (found in http://www-01.ibm.com/support/docview.wss?uid=nas7ba16117761f1f93b86257f73000cff77)

  1. Log on the system as Administrator and open Registry by issuing regedit in the command prompt.
  2. Navigate to [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Static\System].
  3. Find the values which meet the following points: a. “Name” string starts with “SNMP-”. b. “Data” string contains “syswow64\snmp.exe”. c. “Data” string contains “Action=Block”.
  4. Change the “Action=Block” to “Action=Allow” of those entries.
  5. Restart the “Windows Firewall” service by issuing net stop MPSSVC and net start MPSSVC .
  6. Restart the “SNMP Service” service by using net stop SNMP and net start SNMP .

Upvotes: 0

user1688877
user1688877

Reputation: 41

I solved the problem. The issue was due to Windows Service Hardening which did not allow any TCP communication from snmp service (and extensions). This is enforced even if the firewall is turned off.

https://support.microsoft.com/en-us/kb/2771908

Upvotes: 2

Related Questions