Проблемы с соединением SOCKET в службе на Windows 2012

Я унаследовал проект 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. Сервер запускается в отдельном потоке, я предоставил SECURITY_ATTRIBUTE с NULL DACL, чтобы увидеть, если это проблема безопасности.
  3. Пробовал разные порты.
  4. Пробовал тот же серверный код в отдельном обычном приложении. Клиент может подключиться к этому приложению.
  5. Образец серверного приложения при запуске из агента клиент не может подключиться к нему.
  6. Брандмауэр Windows отключен, и у меня не установлено антивирусное программное обеспечение, которое блокировало бы такие подключения.
  7. Проверил соединение снаружи и заметил в Wireshark, что пакет TCP SYN действительно приходит, но на него нет ответа.
  8. В свойствах Process / TCP / IP обозревателя было замечено, что у службы SNMP есть сокет TCP, прослушивающий 127.0.0.1:27015.

Для быстрых тестов я просто делаю telnet к порту 27015.

Мои вопросы:

  1. Что-то явно не так с кодом сервера, который мне не хватает?
  2. Существуют ли в Windows 2012 ограничения безопасности, которые не позволяют службе принимать такие TCP-соединения?
  3. Любые другие советы, комментарии, входы?

Спасибо,

0

Решение

Я решил проблему. Проблема была связана с усилением службы Windows, которое не разрешало TCP-соединение от службы snmp (и расширений). Это применяется, даже если брандмауэр выключен.

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

2

Другие решения

Я мог бы решить это, следуя этим шагам (найден в 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. Найдите значения, которые соответствуют следующим точкам:
    а. Строка «Имя» начинается с «SNMP-».
    б. Строка «Данные» содержит «syswow64 \ snmp.exe».
    с. Строка «Данные» содержит «Действие = Блок».
  4. Измените «Action = Block» на «Action = Allow» для этих записей.
  5. Перезапустите службу «Брандмауэр Windows», введя команду net stop MPSSVC и команду net start MPSSVC.
  6. Перезапустите службу «Служба SNMP», используя сетевой останов SNMP и сетевой запуск SNMP.
0

По вопросам рекламы [email protected]