0

我继承了一个 C++/Windows 项目,其中我们有一个 SNMP 扩展代理(由 snmp 服务加载)。在代理内部,我们正在创建一个简单的 TCP 服务器,我们的客户端应用程序连接到该服务器并为其提供 SNMP 查询/陷阱等数据。这一切似乎在 Windows 2008 上运行良好。但是,在 Windows 2012 上,客户端不能再连接到在代理内部运行的服务器(在 SNMP 服务中)。connect() 失败并出现错误 10013。

我的服务器代码如下所示:

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;
}

选择继续每 3 秒超时一次,没有任何连接被接受。

这是我尝试过的所有方法(没有奏效):

  1. 试图在特定用户帐户中运行服务。
  2. 服务器在一个单独的线程中运行,我提供了一个带有 NULL DACL 的 SECURITY_ATTRIBUTE 来查看它是否是一个安全问题。
  3. 尝试了不同的端口。
  4. 在单独的普通应用程序中尝试了相同的服务器代码。客户端可以连接到此应用程序。
  5. 从代理启动示例服务器应用程序时,客户端无法连接到它。
  6. Windows 防火墙已关闭,我没有安装任何会阻止此类连接的防病毒软件。
  7. 从外部检查连接并在 Wireshark 中观察到 TCP SYN 数据包确实到达但没有响应。
  8. 在 Process Explorer TCP/IP 属性中观察到 SNMP 服务确实具有侦听 127.0.0.1:27015 的 TCP 套接字。

对于快速测试,我只是对端口 27015 进行 telnet。

我的问题是:

  1. 我缺少的服务器代码是否有明显问题?
  2. Windows 2012 中是否存在一些不允许服务接受此类 TCP 连接的安全限制?
  3. 任何其他提示、评论、输入?

谢谢,

4

2 回答 2

2

我解决了这个问题。该问题是由于 Windows 服务强化,它不允许来自 snmp 服务(和扩展)的任何 TCP 通信。即使防火墙关闭,也会强制执行此操作。

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

于 2015-11-19T14:15:38.117 回答
0

我可以按照这些步骤解决它(在http://www-01.ibm.com/support/docview.wss?uid=nas7ba16117761f1f93b86257f73000cff77中找到)

  1. 以管理员身份登录系统并通过在命令提示符下发出 regedit 打开注册表。
  2. 导航到 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Static\System]。
  3. 找出满足以下几点的值: a.“名称”字符串以“SNMP-”开头。湾。“数据”字符串包含“syswow64\snmp.exe”。C。“Data”字符串包含“Action=Block”。
  4. 将这些条目的“Action=Block”更改为“Action=Allow”。
  5. 通过发出 net stop MPSSVC 和 net start MPSSVC 重新启动“Windows 防火墙”服务。
  6. 使用 net stop SNMP 和 net start SNMP 重新启动“SNMP Service”服务。
于 2017-11-10T20:16:24.443 回答