2013-06-20 3 views
3

Сценарий довольно прост:Простой экспедиторская сокет в Linux

Использование TCP/IP я клиент колдунья подключается ко мне (сервер) Я хочу, чтобы передать данные сокет посылает меня в другую розетку ведьмой, я открыл и данные, которые я получаю от этого сокета назад. Просто как прокси.

Прямо сейчас у меня есть 1 нить, которая прослушивает входящее соединение и порождает еще 2 при установлении соединения с клиентом. Я должен использовать механизм для общения в потоках.

Есть ли что-нибудь более простая ведьма, которую я могу использовать в качестве прокси-сервера TCP/IP? У linux есть пересылка сокетов или какой-то механизм?

Спасибо

+1

Зачем создавать два новых потока при входящих соединениях? Одного достаточно, и он может выполнять как отправку, так и прием с обоих соединений. Читайте о неблокирующих сокетах и ​​системном вызове 'select'. –

+0

Что именно вы подразумеваете под чем-то более простым? Сокет не делает ничего волшебного самостоятельно, вам нужно вручную запрограммировать прием и переадресацию трафика. Существует несколько открытых прокси-серверов открытого типа, таких как кальмары. Но они в основном веб-прокси. Не будет работать ни для каких подключений tcp, а скорее для HTTP. – fayyazkl

ответ

3

Вам не нужны нитки. Посмотрите на select(), epoll() или kqueue(), чтобы управлять несколькими сокетами без какого-либо потока (если вы в Windows, это completion port).

This is an example of a select-based server, это будет хорошее начало.

12

Вы можете использовать iptables для выполнения port forwarding. Это не c-решение, но это 2-line, который имеет хорошую производительность и будет иметь минимальную отладку.

От второго звена:

iptables -A PREROUTING -t nat -i eth1 -p tcp \ 
     --dport 80 -j DNAT --to 192.168.1.50:80 

iptables -A INPUT -p tcp -m state --state NEW \ 
     --dport 80 -i eth1 -j ACCEPT 

Первая линия вперед от порта 80 на порт 80 на 192.168.1.50, а второй принимает соединение, сохраняя IPTables от падения его.

Вы можете добавить дополнительные ограничения с другим IPtables флагами, такими как -s 10.0.3.0/24 бы поймать все адреса с источником 10.0.3.0 до 10.0.3.255

+0

Спасибо, но я должен направить трафик на основе входящих ips – opc0de

+1

, вы можете сделать это с помощью дополнительных флагов, например -s –

9

Одно решения на уровне пользователя с помощью socat. Например, чтобы принимать соединения на порт 8080 и пересылать их 192.168.1.50:9090 вы можете использовать:

socat TCP-LISTEN:8080,fork TCP:192.168.1.50:9090 

Опция fork делает socat разрешения нескольких соединений.

+0

Я должен маршрутизировать трафик на основе входящих ips – opc0de

+0

Используя подход 'iptables', вы можете добавить соответствующие правила для адреса источника ('--source'). Для этого в пользовательском пространстве потребуется нечто более совершенное, например, с помощью прокси-программы 'squid'. – Joni

1

Для простой переадресации сокетов пусть это сделает ядро. Используйте iptables или один из интерфейсов для его настройки.

Если вам нужно сложное обнюхивание/перетаскивание данных/пересылка для использования в реальном мире, напишите модуль iptables.

Если вам нужно выполнить тикет (дублировать/разделить) поток данных или просмотреть или изменить данные, тогда прочитайте дальше.

Linux 2.6.17 и более поздние версии, с glibc 2.5 и более поздними версиями, предоставляют несколько приятных функций: splice() и tee(). Вы можете использовать их, чтобы избежать использования полезной нагрузки, скопированной в и из пользовательского пространства, в которой ядро ​​передало определенное количество байтов из одного дескриптора в другой. (tee() не использует данные, позволяющие отправлять одну или несколько копий данных другим дескрипторам.)

Вы можете использовать два потока для каждого соединения (по одному на каждое направление)/tee поток данных по мере необходимости.Когда вы знаете, у вас есть N входящих байтов для пересылки на один исходящий сокет, используйте splice(). Если у вас более одного исходящего сокета, используйте неблокирующие исходящие сокеты, tee() небольшие куски за раз (но используйте splice() для последнего исходящего сокета для каждого фрагмента).

Ваши темы можно прочитать некоторые/все входящие данные, чтобы решить, что делать с ним, но помните, что вам нужно write() или send() часть, которую вы уже прочитали, что нужно отправить, перед использованием splice() или tee(); они не волшебным образом собирают уже потребляемые данные.

Смежные вопросы