Ми багато разів розповідали тобі про проксі-сервери: для чого вони потрібні, як вони працюють і чим корисні хакеру. Проте знати і використовувати - це одне, а ось створювати самому - зовсім інша справа. Ця творча праця корисний для душі, тіла і, звичайно ж, твого WM-гаманця.
трохи теорії
Отже, проксі-сервер - це перш за все програма, яка виступає посередником між клієнтом і сервером. Всі звикли пов'язувати поняття проксі тільки з протоколом HTTP. Насправді існують проксікі і для інших протоколів, про які я розповім трохи пізніше. Найпоширеніший вид проксіков - HTTP. При роботі через HTTP-проксі твій браузер не буде з'єднуватися з сервером, на якому розташований запитуваний сайт, він з'єднається з проксі і передасть йому запит. Отримавши від тебе всі необхідні дані, проксік сам сконнектітся з віддаленим web-сервером і відправить твій запит. Після його обробки web-сервер поверне документ проксіку, який потім відправить його тобі. Такі проксікі корисні, коли потрібна анонімність (оскільки вони бувають прозорими) або якщо твій провайдер обмежує тебе і не дозволяє відвідувати сайти, розташовані на зарубіжних серверах.
Ще одне місце, де постійно використовуються проксі-сервери, - корпоративні (домашні) локальні мережі. Для надання співробітникам компанії доступу в інет адміни встановлюють на шлюзі проксік, і вся контора ходить через нього в Мережу. Плюси такого способу очевидні: можна легко відстежувати маршрути користувачів, рахувати кількість витраченого трафіку і бути впевненим в тому, що користувачі не користуватимуться зайвим софтом, так як не кожна програма здатна працювати через HTTP-проксі.
Я вже говорив, що HTTP-проксі не є єдиним типом проксі-серверів. У природі також зустрічаються:
Навіщо писати свій проксі-сервер
Розібравшись на практиці з основами написання проксі-серверів, ти зможеш поповнити колекцію] [- тулз власного виготовлення. Наприклад, можна без праці зробити проксі абсолютно невидимим в системі. Підсунувши таку штуку сусідові, в разі якщо він не думає про security і не юзает файрвол, хакер без проблем зможе ганяти інет-трафік через його комп, насолоджуючись халявою.
Іншим цікавим способом застосування твого шедевра може бути сніфаніе хакером паролів, які сусід вводить в своєму браузері. В цьому випадку хакеру також потрібно буде підкинути нещасному сусідові твою ТУЛЗ і переконати його запустити її. Після запуску] [- проксік автоматично сконфигурирует бродилку сусіда на роботу через самого себе. Тим самим чол буде спокійно борознити інет, а все його запити (відправка паролів і т.д.) будуть записуватися лог. Круто? Безсумнівно! Але ми-то з тобою знаємо, що всі ці маревні ідеї носять протизаконний характер, тому ми будемо писати проксі-сервер лише в освітніх цілях, навіть і не думаючи про отримання вигоди.
використовувані технології
При написанні серверних мережевих додатків не рекомендується використовувати компонентну модель Delphi. Компоненти не володіють тією гнучкістю, яку можна отримати, застосовуючи API. Тому сьогодні нам знову доведеться зіткнутися зі страшним WinSock API.
Тепер давай обговоримо алгоритм роботи нашого майбутнього проксі-сервера. Оскільки ми будемо створювати серверний додаток, йому просто необхідно бути розрахованих на багато користувачів. Ти тільки уяви корпоративний проксі-сервер, яким може користуватися тільки одна людина, а решта тим часом будуть нервово курити в стороні. Отже, раз наш додаток буде розрахованих на багато користувачів, то оптимально використовувати потоки. При підключенні клієнта для нього буде створюватися окремий потік. Таким чином наш сервер зможе одночасно працювати з декількома користувачами.
Обговоримо отримання запиту від клієнта. У запиті, який формує браузер, міститься інформація, на підставі якої web-сервер може визначити, який саме web-документ ми від нього хочемо. Всі нюанси запитів ти можеш дізнатися з RFC 2068. Розглянемо приклад. Коли ти набираєш в браузері www.xakep.ru, запит має наступний вигляд (може відрізнятися, залежить від браузера):
Winsock API для Proxy
Як і личить в програмуванні, після обговорення алгоритму вирішення поставленого завдання, потрібно визначитися з інструментами, які будуть необхідні для цього. У нашому випадку головним молотком буде Delphi, а цвяхами з шурупами - WinSock API і класи TThread. Розглянемо необхідні WinSock API функції.
Ця функція, з виклику якої потрібно починати програмування будь-якого мережевого додатки. Вона призначена для ініціалізації мережевої бібліотеки Windows. Функції необхідно заслати два параметри:
При успішному виконанні функція поверне 0. Для отримання кодів помилок в WinSock API служить функція WSAGetLastError (). Їй не потрібно передавати будь-які параметри, після виклику вона повертає код останньої виникла при роботі з мережевими функціями помилки.
Перед тим як з'єднатися з віддаленим вузлом, потрібно створити «розетку» - socket. Якраз за його створення і відповідає однойменна функція socket. Вхідних параметрів три:
Результатом виконання буде новий сокет. Створивши сокет, можна пробувати підключатися. Для цього в бібліотеці реалізована функція Connect.
Параметрами для функції служать:
Успішно виконати, а значить, і встановивши з'єднання, функція поверне 0, в іншому випадку - помилку, яку можна отримати за допомогою WSAGetLastError ().
Структура TSockAddr виглядає так:
Читання і відправка даних лише у віддаленій стороні здійснюється за допомогою функцій send і recv. Вони описані в такий спосіб:
Параметри для обох функцій однакові:
Виконати, функція поверне фактична кількість відправлених / прийнятих байт.
Призначення функції - зв'язування структури TSockAddr зі створеним сокетом. Параметрів три: сокет, структура, розмір структури.
Фактичне прослуховування порту починається після виклику цієї функції. Для роботи функції потрібно всього два параметри: сокет і максимальну кількість запитів на очікування підключення.
Ця функція закриває сокет. Параметр всього один - сокет, який потрібно закрити.
Мета функції - перевірка готовності сокета (читання, запис термінових даних). Select дуже пригождается, коли потрібно розробляти розраховані на багато користувачів мережеві додатки подібно до нашого, де використання подієвої моделі Windows не виправдовує себе. Як параметри функція приймає:
Очищення і ініціалізація набору сокетов. Перед додаванням сокетов в набір необхідно його проинициализировать за допомогою цієї функції.
Процедура призначена для додавання сокета, переданого в першому параметрі в набір, зазначений у другому.
Функція дозволяє перевірити входження сокета (перший параметр) в набір (другий параметр).
Ось і настала та заповітна хвилина, коли ми закінчуємо розбиратися з теорією і приступаємо до реального КОДІНГ. Запускай Delphi, створюй новий проект і додай формі вид, схожий на вигляд моєї форми. Ми не будемо нічого приховувати від користувача, оскільки, якщо ти пам'ятаєш, ми пишемо програму в освітніх цілях. Ти там далі сам розберешся. На формі у мене три кнопки:
Цією однієї-єдиної рядком коду ми створюємо новий потік типу TListenThread. Потоки можна створювати припиненими. Саме тому в якості параметра методу Create я передаю значення false, що вимагає негайного запуску.
Потік TListenThread підготує сокет для прослуховування і чекатиме підключень на порт 8080. Код створення наведено в урізанні «Потік TListenThread».
Давай докладніше розглянемо вміст наведеної вище врізки. Процедура Execute (). певна у об'єкта TlistenThread. є основною для потоків. Після запуску потоку вона виконується найпершої, а раз так, то саме в ній потрібно розташувати код, який відповідає за початок прослуховування певного порту.
Щоб почати слухати порт, потрібно створити сокет за допомогою однойменної функції socket (). Параметри, необхідні для роботи функції, визначаються виходячи з того, який протокол ми будемо використовувати. HTTP-проксік повинен задіяти TCP / IP-протокол, що забезпечує надійну передачу даних. Тому в другому параметрі я вказую SOCK_STREAM.
Створивши сокет, потрібно переконатися, що після виконання функції Socket не відбулася помилка. Для перевірки досить порівняти змінну сокета зі значенням константи INVALID_SOCKET. Якщо вони виявляться рівними, то сталася помилка і подальше виконання програми безглуздо. Припустимо, що сокет успішно створився, а значить, наступним кроком буде заповнення структури sockaddr_in, що містить необхідні дані для початку прослуховування.
Детальний опис всіх властивостей структури я вже наводив, тому зараз не буду загострювати на цьому увагу. Заповнивши всі властивості структури, її потрібно зв'язати з нашим сокетом за допомогою функції BIND. Якщо функція BIND виконалася без помилок, то треба викликати функцію для початку прослуховування - Listen. Після її виконання запускається нескінченний цикл, в якому викликається функція accept (). Успішне її виконання буде означати, що до нас приєднався клієнт, і для роботи з ним необхідно створити новий потік. У потоці TClientThread відбуватиметься обмін даними між клієнтом і нашим проксіком і, відповідно, між проксіком і віддаленим сервером. Основний код потоку TClientThread наведено в урізанні, а повну версію ти завжди можеш подивитися на нашому диску.
Код потоку TClientThread
Як тільки з'єднання буде встановлено, потрібно перевести сокет в асинхронний режим. Зміна режиму відбувається за допомогою функції setsockopt (). Переклад в асинхронний режим необхідний, оскільки в такому випадку нехило підвищиться продуктивність нашого застосування. Це стане можливим через мінімізацію затримок перед пересиланням даних між нами, web-сервером і клієнтом. Отримавши від сервера порцію даних, ми не будемо чекати інших, а будемо відразу відправляти її клієнту.
Слухове вікно прорублене
Сподіваюся, сьогоднішній приклад вийшов досить корисним як для програміста, так і для хакера. В черговий раз ти переконався, що Delphi - це не тільки бази даних і звіти, але і мову, за допомогою якого можна вирішувати як прикладні, так і хакерські завдання. Мені залишається тільки побажати тобі успішного застосування отриманих знань в своїх майбутніх проектах.