Определение ip адреса удаленного компьютера в терминальной сессии через win api

Clarion, Clarion 7

Модератор: Дед Пахом

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Ответить
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 5078
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 11 раз
Поблагодарили: 50 раз

Определение ip адреса удаленного компьютера в терминальной сессии через win api

Сообщение finsoftrz »

Это, наверно, надо смотреть в сторону WinStationQueryInformation. Может у кого есть пример работы на кларионе? Или другие способы без вызова внешних скриптов.
C6/C11, ШВС, tps/btrieve.
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 7867
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 28 раз
Поблагодарили: 85 раз

Определение ip адреса удаленного компьютера в терминальной сессии через win api

Сообщение Игорь Столяров »

А через штатные функции Winsock API здесь не получится работать ?
У меня нет терминального сервера для проверки ...
Например как вот здесь: https://attryde.com/clarion/col_tcpip.htm
Make Clarion Great Again ! 😎
kreator
✯ Ветеран ✯
Сообщения: 5119
Зарегистрирован: 28 Май 2009, 15:54
Откуда: Москва
Благодарил (а): 11 раз
Поблагодарили: 23 раза

Определение ip адреса удаленного компьютера в терминальной сессии через win api

Сообщение kreator »

Мы вытаскивали из реестра. Вроде проблем не наблюдали. Правильно ли я понимаю. Рабочая станция, которая вошла через rdp, должна сообщить свой ip-адрес?
We are hard at work… for you. :)
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 5078
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 11 раз
Поблагодарили: 50 раз

Определение ip адреса удаленного компьютера в терминальной сессии через win api

Сообщение finsoftrz »

kreator писал(а): 02 Март 2025, 22:55 Мы вытаскивали из реестра. Вроде проблем не наблюдали. Правильно ли я понимаю. Рабочая станция, которая вошла через rdp, должна сообщить свой ip-адрес?
Да, правильно. Из того, что я успел прочитать, есть 2 адреса. Один, который передает удаленный компьютер, второй реальный адрес, который определяет система при подключении. Винда знает оба. Нужен второй. Смысл в том, чтобы можно на уровне приложения устанавливать разрешение для пользователя входить с определенного ip адреса или блокировать какие-то ip адреса. Обычно для этих целей используют отдельные сторонние продукты, но хотелось бы все иметь в одном флаконе, проще управлять и контролировать.
C6/C11, ШВС, tps/btrieve.
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 5078
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 11 раз
Поблагодарили: 50 раз

Определение ip адреса удаленного компьютера в терминальной сессии через win api

Сообщение finsoftrz »

В интернете есть такой пример на c. ХЗ, как это в кларионе может выглядеть.

Код: Выделить всё

typedef enum _WINSTATIONINFOCLASS {
    // ...
    WinStationRemoteAddress = 29,
    // ...
} WINSTATIONINFOCLASS;

#define LOGONID_CURRENT     ((ULONG)-1)

typedef struct {
    unsigned short sin_family;
    union {
        struct {
            USHORT sin_port;
            ULONG in_addr;
            UCHAR sin_zero[8];
        } ipv4;
        struct {
            USHORT sin6_port;
            ULONG sin6_flowinfo;
            USHORT sin6_addr[8];
            ULONG sin6_scope_id;
        } ipv6;
    };
} WINSTATIONREMOTEADDRESS,
*PWINSTATIONREMOTEADDRESS;

EXTERN_C
DECLSPEC_IMPORT
BOOLEAN
WINAPI
WinStationQueryInformationW(
                            _In_opt_ HANDLE hServer,
                            _In_ ULONG SessionId,
                            _In_ WINSTATIONINFOCLASS WinStationInformationClass,
                            _Out_writes_bytes_(WinStationInformationLength) PVOID pWinStationInformation,
                            _In_ ULONG WinStationInformationLength,
                            _Out_ PULONG pReturnLength
                            );

ULONG GetRdpClientAddressFromServerView()
{
    ULONG dwError = NOERROR;
    ULONG cb;

    union {
        SOCKADDR sa;
        SOCKADDR_IN sa4;
        SOCKADDR_IN6 sa6;
    };

    WINSTATIONREMOTEADDRESS ra;

    if (WinStationQueryInformationW(0, LOGONID_CURRENT, WinStationRemoteAddress, &ra, sizeof(ra), &cb))
    {
        switch (sa.sa_family = ra.sin_family)
        {
        case AF_INET:
            sa4.sin_port = ra.ipv4.sin_port;
            sa4.sin_addr.S_un.S_addr = ra.ipv4.in_addr;
            RtlZeroMemory(sa4.sin_zero, sizeof(sa4.sin_zero));
            cb = sizeof(SOCKADDR_IN);
            break;
        case AF_INET6:
            sa6.sin6_port = ra.ipv6.sin6_port;
            sa6.sin6_flowinfo = ra.ipv6.sin6_flowinfo;
            memcpy(&sa6.sin6_addr, &ra.ipv6.sin6_addr, sizeof(in6_addr));
            sa6.sin6_scope_id = ra.ipv6.sin6_scope_id;
            cb = sizeof(SOCKADDR_IN6);
            break;
        default:
            dwError = ERROR_GEN_FAILURE;
        }

        if (dwError == NOERROR)
        {
            // assume that WSAStartup already called
            // WSADATA wd;
            // WSAStartup(WINSOCK_VERSION, &wd);

            char AddressString[64];
            ULONG dwAddressStringLength = _countof(AddressString);
            if (WSAAddressToStringA(&sa, cb, 0, AddressString, &dwAddressStringLength) == NOERROR)
            {
                DbgPrint("client ip is %s\n", AddressString);
            }
            else
            {
                dwError = WSAGetLastError();
            }
        }
    }
    else
    {
        dwError = GetLastError();
    }

    return dwError;
}

C6/C11, ШВС, tps/btrieve.
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 5078
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 11 раз
Поблагодарили: 50 раз

Определение ip адреса удаленного компьютера в терминальной сессии через win api

Сообщение finsoftrz »

Решил спросить у DeepSeek, давно была мысль его на перевод с win api попробовать. :-) Вот что выдал (прототип и пример использования).

Код: Выделить всё

MODULE('USER32')
  WinStationQueryInformationW(ULONG, ULONG, WSTRING, ULONG, ULONG),BOOL,RAW,PASCAL,NAME('WinStationQueryInformationW')
END

Код: Выделить всё

LOCAL(infoBuffer AS WSTRING(256))
LOCAL(bufferSize AS ULONG)
LOCAL(result AS BOOL)

bufferSize = SIZEOF(infoBuffer)
result = WinStationQueryInformationW(0, 0, 'WinStationInfo', infoBuffer, bufferSize)

IF result THEN
  MESSAGE('Информация успешно получена: ' & infoBuffer)
ELSE
  MESSAGE('Ошибка при получении информации')
END
C6/C11, ШВС, tps/btrieve.
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 5078
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 11 раз
Поблагодарили: 50 раз

Определение ip адреса удаленного компьютера в терминальной сессии через win api

Сообщение finsoftrz »

Пример для получения ip адреса. Правда пишет, что нужны права администратора.

Код: Выделить всё

MODULE('USER32')
  WinStationQueryInformationW(ULONG, ULONG, ULONG, *GROUP, ULONG, *ULONG),BOOL,RAW,PASCAL,NAME('WinStationQueryInformationW')
END

WTS_CLIENT_ADDRESS GROUP, TYPE
  AddressFamily  ULONG
  Address       BYTE(20)
END

LOCAL(clientAddress AS WTS_CLIENT_ADDRESS)
LOCAL(returnedLength AS ULONG)
LOCAL(result AS BOOL)

! Запрашиваем информацию о клиентском адресе
result = WinStationQueryInformationW(0, 0, 14, ADDRESS(clientAddress), SIZEOF(clientAddress), ADDRESS(returnedLength))

IF result THEN
  ! Извлекаем IP-адрес из структуры
  LOCAL(ipAddress AS STRING(16))
  ipAddress = FORMAT(clientAddress.Address[2]) & '.' & FORMAT(clientAddress.Address[3]) & '.' & FORMAT(clientAddress.Address[4]) & '.' & FORMAT(clientAddress.Address[5])
  MESSAGE('IP-адрес клиента: ' & ipAddress)
ELSE
  MESSAGE('Ошибка при получении IP-адреса клиента')
END
C6/C11, ШВС, tps/btrieve.
Аватара пользователя
Дед Пахом
Старичок
Сообщения: 3267
Зарегистрирован: 07 Июль 2005, 16:51
Откуда: Москва, Россия
Благодарил (а): 15 раз
Поблагодарили: 48 раз
Контактная информация:

Определение ip адреса удаленного компьютера в терминальной сессии через win api

Сообщение Дед Пахом »

А это не смущает?
[WinStationQueryInformationW is not supported and may be altered or unavailable in the future. Instead, use the GetSystemMetrics function with SM_REMOTESESSION to obtain this information (see Detecting the Remote Desktop Services Environment). ]
С уважением, ДП
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 5078
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 11 раз
Поблагодарили: 50 раз

Определение ip адреса удаленного компьютера в терминальной сессии через win api

Сообщение finsoftrz »

Дед Пахом писал(а): 03 Март 2025, 16:37 А это не смущает?
[WinStationQueryInformationW is not supported and may be altered or unavailable in the future. Instead, use the GetSystemMetrics function with SM_REMOTESESSION to obtain this information (see Detecting the Remote Desktop Services Environment). ]
Автор примера написал, что это работает на всех версиях винды. Ему такой же вопрос задали. Потом автор вопроса попробовал, отписался, что все норм.
DeepSeek, конечно, полную ахинею написал.
C6/C11, ШВС, tps/btrieve.
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 5078
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 11 раз
Поблагодарили: 50 раз

Определение ip адреса удаленного компьютера в терминальной сессии через win api

Сообщение finsoftrz »

В списке запросов GetSystemMetrics получения адреса не увидел, специально проверил.
C6/C11, ШВС, tps/btrieve.
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 5078
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 11 раз
Поблагодарили: 50 раз

Определение ip адреса удаленного компьютера в терминальной сессии через win api

Сообщение finsoftrz »

На всякий случай напишу, что утилита GETTSCIP.exe не подходит для этих целей, так как она возвращает адрес компьютера в локальной сети, а не внешний ip адрес компьютера, с которого делается терминальное подключение.
C6/C11, ШВС, tps/btrieve.
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 5078
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 11 раз
Поблагодарили: 50 раз

Определение ip адреса удаленного компьютера в терминальной сессии через win api

Сообщение finsoftrz »

Подумал, подумал, сделал пока проверку через GETTSCIP.exe. Может, позже что-то получится с определением внешнего ip адреса.
C6/C11, ШВС, tps/btrieve.
Аватара пользователя
Admin
Администратор
Сообщения: 4009
Зарегистрирован: 05 Июль 2005, 15:59
Откуда: Хабаровск
Благодарил (а): 51 раз
Поблагодарили: 30 раз
Контактная информация:

Определение ip адреса удаленного компьютера в терминальной сессии через win api

Сообщение Admin »

Смысл в том, чтобы можно на уровне приложения устанавливать разрешение для пользователя входить с определенного ip адреса или блокировать какие-то ip адреса.

Обратите внимание что клиент(ы) может сидеть за NAT и в таком случае в получите не совсем верную информацию.
Обычно для этих целей используют отдельные сторонние продукты, но хотелось бы все иметь в одном флаконе, проще управлять и контролировать.
Сторонние продукты м.б. заточены на идентификацию по многим признакам.
Рай совершает ошибки ничуть не реже чем ад. Просто у него хорошая пресса
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 5078
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 11 раз
Поблагодарили: 50 раз

Определение ip адреса удаленного компьютера в терминальной сессии через win api

Сообщение finsoftrz »

Там 2 варианта задачи.
Первый сделать возможным вход в приложение пользователя, подключающегося только с определенного ip адреса. Сейчас я сделал, как написал, через gettscip.exe. Эта утилита возвращает тот ip адрес, который передает на сервер удаленный компьютер. Если она за роутером, то это будет адрес компьютера в локальной сети, то есть что-то типа 192.168.1.88. Внешний ip адрес, с которого происходит подключение к серверу, будет другой. Для первого варианта задачи, в принципе, такой вариант можно использовать, так как внутренний адрес в сети можно согласовать с клиентом.

Второй это запрет или разрешение входа в программу с определенных ip адресов. Для этих целей нужен внешний ip адрес удаленного компьютера, и gettscip.exe не подойдет. В интернете я нашел только информацию с WinStationQueryInformationW, про это как-то очень скудно пишут. Может, есть и еще какие-то варианты. Нужно ли включать в приложение такую проверку, это открытый вопрос, так как эта проверка будет работать после запуска кларионовского приложения, предпочтительнее ее проводить до этого. Для tsplus есть отдельный продукт tsplus advanced security (за отдельную плату), который как раз таким, в том числе, и занимается. По сути, это все держится на достаточно простой настройке, если удастся определить внешний ip адрес.

Другие фишки для входа в приложение у меня есть. Это отключение выбора из списка пользователей и ввод имени пользователя напрямую в окне подключения (как в винде), запрет подключения определенным пользователям в режиме терминального сервера, запрет доступа к файловой системе сервера из приложения, ограничение подключения по часам в течении дня, запрет подключения в выходные дни, автоматическая блокировка на определенное время после заданного количества неудачных попыток авторизации.
C6/C11, ШВС, tps/btrieve.
Ответить