2015-05-25 2 views
6

Цель состоит в том, чтобы программа перехватила коллекцию IP-пакетов и прочитала ее необработанное содержимое, а затем повторно ввела его в сеть после того, как переделала его.Ввод/вывод с интерфейсом Tun

Мой подход основан на настройке интерфейса Tuntap (Tun, для конкретных), а затем iptables и аналогичных перенаправлять нужные пакеты в этот интерфейс туннеля.

Для целей тестирования я написал этот короткий сценарий оболочки, который настраивает интерфейс Tun и добавляет необходимые правила. На данный момент я намерен проверить это на любом пакете, отправленном с моего локального компьютера, с адресом 123.123.123.123. Вот сценарий запуска:

# Set up the tunnel 
ip tuntap add dev maintun mode tun 
ifconfig maintun inet 10.10.10.1 netmask 255.255.255.0 up 

# Mark packets for forwarding to tun 
iptables -t mangle -A PREROUTING -d 123.123.123.123 -j MARK --set-mark 2 

# Apply ClientRouter table to mark 2 as it's defined in /etc/iproute2/rt_tables 
# 201 ClientRouter 
ip rule add fwmark 2 table ClientRouter 

# Apply gw if to ClienRouter 
ip route add default via 10.10.10.1 dev maintun table ClientRouter 

Я начал писать PERL скрипт для чтения из устройства тун, но я застрял на несколько пунктов сразу:

  1. Мне кажется, что путь сделайте это, чтобы сам скрипт создавал интерфейс, вызывая ioctl() на дескрипторе файла до /dev/net/tun, но я не уверен в других аргументах ioctl(). Это приводит меня к следующим двум точкам:
  2. Я вижу ссылки на второй аргумент TUNSETIFF. Все, что я знаю, это то, что оно должно быть числовым. Что он просит?
  3. Из того, что я собрал, третий аргумент должен быть каким-то флагом, но мне не удалось найти информацию о них. Предположительно, один флаг будет выбирать, должен ли он быть туннелем Tun или Tap. Любая информация об этом?

Как я привязался к знаку ioctl(), я хотел бы сделать шаг назад и спросить: как программно читать с устройства Tun, желательно предварительно настроенного заранее?

Кроме того, если кто-то видит что-то не так со стартовым скриптом, не стесняйтесь кричать.

В то время как в идеале разрешение будет в perl, оно не обязательно должно быть, это просто тот язык, который я могу прочесть самым простым. Java также будет приличной. К сожалению, моя C-грамотность даже не близка к такой хорошей, как это должно быть для этого.

Edit:

Если другой подход, чем Tun/Tap позволит мне делать, как описано в первом абзаце, любые предложения, конечно, будет приветствоваться.


Примечание:

Я пришел крест this question и в то время как аналогичный, он не дает ответа на IOCTL() заданы параметры. Это, однако, указывало на необходимость вызова ioctl().

+1

Вы также можете быть заинтересованы в использовании libnetfilter_queue/NFQUEUE. см. https://home.regit.org/netfilter-en/using-nfqueue-and-libnetfilter_queue/ для краткого обсуждения. –

ответ

3

Во-первых, интерфейс TUN/TAP документирован in the Linux kernel documentation, который стоит прочитать, если вы еще этого не видели. Примеры в C, конечно, но, надеюсь, все же полезны.

Я вижу ссылки на второй аргумент TUNSETIFF. Все, что я знаю, это то, что оно должно быть числовым. Что он просит?

Это постоянная библиотека C, значение которого можно определить, с кодом, как следующее:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <sys/ioctl.h> 
#include <linux/if.h> 
#include <linux/if_tun.h> 

int main(int argc, char **argv) { 
    printf("TUNSETIFF: %d\n", TUNSETIFF); 
    return 0; 
} 

Который на моей системе возвратов:

TUNSETIFF: 1074025674 

От чего Я собрал, третий аргумент должен быть каким-то флагом, но мне не удалось найти информацию о них. Предположительно, один флаг будет выбирать, должен ли он быть туннелем Tun или Tap. Любая информация об этом?

Третий аргумент является указателем на структуру, которая имеет ifr_name атрибут, содержащий имя устройства, а также атрибут ifr_flags , содержащий флаги. Документация ядра обеспечивает следующий код:

/* Flags: IFF_TUN - TUN device (no Ethernet headers) 
    *  IFF_TAP - TAP device 
    * 
    *  IFF_NO_PI - Do not provide packet information 
    */ 
    ifr.ifr_flags = IFF_TUN; 
    if(*dev) 
    strncpy(ifr.ifr_name, dev, IFNAMSIZ); 

    if((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0){ 
    close(fd); 
    return err; 
    } 

Вы можете найти значения для различных флагов (IFF_TUN, IFF_TAP) , используя один и тот же код из выше, что мы использовали, чтобы найти значение TUNSETIFF.

Если вы пишете код в Perl, вам понадобится способ создания соответствующей C-совместимой структуры . Мой Perl слишком ржавый, чтобы предложить правильное решение с головы.

Тем не менее, как представляется, ряд модулей Perl доступны, что упростить весь процесс: