|
C/C++ Миниатюрный сокс-сервер Николай "GorluM" Андреев Xakep, номер #054, стр. 054-088-2 } Нулевой байт будет означать, что клиентский sock4-запрос окончен, и нашему проксику пора соединиться с адресом назначения dwDesIp. Если соединение прошло успешно, мы создаем канал данных между начальным и конечным пунктом. Если же соединение не удалось, то сервер просто убьет созданный ранее сокет при помощи WinSock-функции closesocket. Пишем Для работы sock4-сервера, помимо главного потока, создающегося из EntryPoint виндами (в нем мы слушаем порт), нам потребуется еще один поток. Через него будет производиться коннект и пересылка данных от отправителя к получателю. Из статьи в ][ 12.02 "Пишем своего трояна" ты уже должен знать, как создавать сокет и слушать порт. На этот раз нам придется немного модифицировать механизм приема новых соединений. Функцию accept, ожидающую подключений на указанный порт и возвращающую сокет, мы должны будем запихнуть в бесконечный цикл. А в самом цикле при новом соединении создадим тред и передадим ему полученный сокет. Выглядит это так: while (true) { CreateThread(0,0,secthread,(LPVOID)accept(s, 0, 0), 0, &a); } где secthread - имя треда для обработки соединения, s - сокет, слушающий порт. Теперь, если кто-то приконнектится к открытому порту, сервер создаст нить (thread), в которую передаст переменную типа SOCKET для работы с новым соединением. С главным потоком все ясно, а вот как обстоят дела с побочным, мы сейчас выясним. Для более удобного объявления треда я создал небольшой макрос: #define _Thread(x) unsigned long __stdcall x (LPVOID pParam) И теперь, если необходимо создать тред, достаточно написать: _Thread (имя_нити). Но на этом способе облегчения кодинга я не остановился. Пользуясь Visual Studio .NET, я откопал немало очень интересных для си-кодера фишек. Вот одна из них: user keyword, по-русски - пользовательские ключевые слова. Они позволяют выделить в VS определенные слова каким-нибудь цветом (см. скрин). Я ими активно пользуюсь и тебе советую. Если ты юзаешь свои макросы, то очень удобно сделать их выделяющимися в тексте программы. Для добавления ключевых слов достаточно создать файл usertype.dat в директории, где лежит твоя VS.NET, в Common7\IDE, и записать notepad'ом в него нужные ключевые слова по одному в строке. После этого перезагрузи VS.NET и радуйся красивому сорцу. Но вернемся к нашим баранам. В созданной нити мы будем обрабатывать входящие соединения и при необходимости создавать новые коннекты с серверами, указанными в запросах. Вот как это происходит. Сначала принимаем один байт, в нем содержится версия требуемого сокс-протокола. Причем получим этот байт, не удаляя его из очереди сообщений. Для этого при вызове winsock-функции recv в четвертом параметре передадим значение MSG_PEEK. Теперь, при следующем чтении из сокета, мы сначала получим этот же байт и только потом все остальное. Это необходимо для отброса лишних байт при проверке версии. Итак, если версия равна четырем, то заполним структуру socks4Request типа SOCKS4_REQUEST из нашего сокета: recv(s, (char*)&socks4Request, sizeof(socks4Request), 0); |