Показаны сообщения с ярлыком linux. Показать все сообщения
Показаны сообщения с ярлыком linux. Показать все сообщения

вторник, 1 января 2013 г.

Пример перехвата сетевого траффика с помощью Raw Sockets

Иногда бывает необходимость в получении сырых данных поступающих на сетевой интерфейс. Один из вариантов решения задачи — создать сетевой драйвер использующий интерфейсы netfilter. Хотя этот вариант будет иметь наибольшую производительность, существует более простой путь с точки зрения реализации. Для этого не надо писать никаких драйверов, достаточно просто открыть Raw Socket (сырой сокет) в программе рижима пользователя.

Ниже приведён пример программы, печатающей на экран весь входящий трафик:


#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <linux/if_ether.h> // ETH_P_ALL
#include <linux/if_packet.h> // sockaddr_ll

int main(int argc, char **argv)
{
    int s;
    struct sockaddr_in src_addr;
    char packet[50] = {0};
    struct sockaddr_ll    sll = {0};

    if ((s = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) < 0) { // (1)
        perror("socket");
        return -1;
    }

    sll.sll_family        = AF_PACKET;
    sll.sll_ifindex        = 3; // Interface index (2)
    sll.sll_protocol    = htons(ETH_P_ALL);

    if( bind(s, (struct sockaddr *) &sll, sizeof(sll)) == -1 ) {
        perror("bind");
    }

    socklen_t *len = (socklen_t *)sizeof(src_addr);
    int fromlen = sizeof(src_addr);

    while(1) {
        if (recvfrom(s, &packet, sizeof(packet), 0,
                    (struct sockaddr *)&src_addr, &fromlen) < 0)
            perror("recvfrom");

        int i = sizeof(struct iphdr); // print the payload

        for(; i < sizeof(packet); i++) {
            printf("%02X ", (unsigned char) packet[i]);
        }

        printf("\n");
    }
    return 0;
}
 

Комментарии:

  1. Чтобы открыть сырой сокет, необходимы права суперпользователя. 
  2. Номер интерфейса можно получить в том числе командой "ip addr sh"
Код тестировался на Ubuntu 12.04 x64

Ссылки:

  1. Код основан на примере из ответа на stackoverflow . Оригинальный код у меня не заработал и я его немного изменил.
  2.  libpcap использует этот-же механизм для перехвата траффика (pcap-linux.c/activate_new()). Эту библиотеку используют такие популярные утилиты как tcpdump и wireshark.

среда, 7 декабря 2011 г.

Как получить список изменённых файлов в Linux

Предположим у нас есть папка с исходным набором файлов ${ORIG} и рабочая папка ${ORIG_WITH_CHANGES}, в которую изначально были скопированы файлы из ${ORIG} и произведены некоторые изменения. Задача состоит в том, чтобы получить третью папку ${CHANGES}, которая содержала бы только изменённые файлы с сохранением структуры папок.

Добиться поставленной задачи нам поможет команда rsync:

rsync --progress --exclude out -a -c \
        --compare-dest=${ORIG} ${ORIG_WITH_CHANGES} ${CHANGES} 
cd ${CHANGES} 
find -depth -type d -empty -delete
find . -name .git -print0 | xargs -0 rm -rf

Использованные параметры команды rsync:
--progress: с этим ключём rsync печатает список обработанных файлов во время работы
--exclude out: игнорировать папку out
-a: включает архивный режим. Это сокращение к следующей комбинации ключей: -rlptgoD
-с: игнорировать время изменения и проверять изменился ли файл, сравнивая его побитно с оригиналом.
--compare-dest=${ORIG}: по умолчанию rsync первый раз скопирует все файлы в папку ${CHANGES}. Нам же нужны только изменённые по сравнению с оригиналом. Эта опция включает сравнение с оригиналом

Первая строка  создаёт искомую директорию, но помимо изменённых файлов, она ещё хранит кучу пустых папок. Следующие две команды очищают ${CHANGES} от пустых папок и удаляют все папки с названием ".git".

Эта заметка основана на ответах к моему вопросу на unix.stackexchange.com.

вторник, 6 декабря 2011 г.

Автоматическая пересборка проекта при изменении файлов

Данная задача актуальна в первую очередь вэб-проектам — в данном случае сборка обычно заключается в быстром препроцессинге и копировании файлов, так что хочется чтобы она происходила постоянно при каждом изменении файлов. В Django например подобная функциональность встроена в его вэб-сервер, который следит за изменениями файлов в проекте и перезапускает сам себя, если таковые обнаружит. Если же, как в моём случае, никакого django не используется, а применяется простой GNU Make, приходится прибегать к встроенной возможности ОС Linux — инструменту inotify.

Итак, если вы используете Ubuntu, надо установить пакет inotify-tools — оттуда нам понадобится утилита inotifywait. Получается вот такой Makefile:

.PHONY: watch ❶

all:
    echo "Make all called!"

watch:
    while inotifywait -e modify -r ../ \
        --exclude "(\./build/.*|.*\.swp)" ; \
    do make -C $(CURDIR); done # Call this Makefile again with default target
  1. Отмечаем нашу цель как .PHONY — это значит что она не создаёт никаких файлов и будет выполнена в любом случае (даже если файл watch уже существует)
  2. Конкретно в нашей целе мы бесконечно ждём события modify в папке уровнем выше, за исключением папки "build" (в ней находится этот Makefile) и файлов с расширением .swp (их создаёт редактор Vim  и постоянно обновляет, при каждом введённом символе).
    Если это событие наступает, мы воплняем цель по умолчанию из этого же Makefile (по умолчанию это цель all)
Похожий вопрос на Superuser.com.

среда, 23 февраля 2011 г.

Сравнение вещественных чисел в bash

Я продолжаю писать инструмент для слежения за самодельным вэб-сервером.
Сегодня наткнулся на новую особенность bash — он не умеет работать с вещественными числами (с плавующей точкой). Например он не может их сравнивать:
if [ 0.1 -gt 0.3 ]

возвращает ошибку «bin/run.bash: строка 44: [: 0.1: ожидается числовое выражение».
Пользователь MoneyCat пишет что лучше для этого использовать операторы <, >, <=, >=:
if [ 0.1 > 0.3 ]

Ошибка хоть и перестала появляться, но зато скрипт начал просто неверно работать.
Как нам дружелюбно напоминает Advanced Bash-Scripting Guide:
Bash does not understand floating point arithmetic. It treats numbers containing a decimal point as strings.
Чтобы обойти это ограничение можно воспользоваться bc:
if [ $(echo "$max < $i" | bc) -eq 1 ]


Теперь мой скрипт так же умеет следить и за загрузкой процессора. Он получает % от используемого моей программой процессорного времени в виде вещественного числа от команды ps:
CPUUSE=$(ps h -p $TARG_PID -o pcpu)

Слежение за процессом из bash скрипта

Я решил поднять у себя на машине самодельный веб-сервер. Естественно хочется чтобы он не мешал во время работы, а так как сервер самодельный риск всяких утечек памяти и зацикливаний высок — нужно средство слежения которое в критический момент будет убивать мою поделку.
В качестве языка я выбрал bash, т.к. программы на нём жрут очень мало ресурсов.

Пока делал эту прогу, мне показались интересными три момента:
  1. Отлавливание сигналов происходит при помощи команды trap
    trap "echo Hello world" SIGHUP SIGINT SIGTERM
  2. Самым надёжным способом выяснить в какой папке лежит сам скрипт является команда lsof
    LSOF=$(lsof -p $$ | grep -E "/"$(basename $0)"$")
    MY_PATH=$(echo $LSOF\
    | sed -r s/'^([^\/]+)\/'/'\/'/1 2>/dev/null)
    MY_ROOT=$(dirname $MY_PATH)
  3. Судя по всему самый надёжный способ узнать сколько памяти занимает процесс — это сложить значения RSS и Dirty команды pmap
    MEMUSE_RAW=$(pmap -x $TARG_PID 2>/dev/null | grep total\
    | sed 's/-//g' | sed s/[^0-9\ ]*//g);
    RSS=$(echo $MEMUSE_RAW | awk '{print $2}')
    DIRTY=$(echo $MEMUSE_RAW | awk '{print $3}')
    MEMUSE=$(echo $RSS+$DIRTY | bc)
Весь код скрипта:

пятница, 7 августа 2009 г.

mmsh и ubuntu 9.04 jaunty

Однажды меня попросили записать передачу с литовского телеканала. Всё казалось бы просто — взял vlc и вперёд... но не тут-то было! Канал этот вещается в фомате mmsh (?) и встроенным плагином видео никак не игралось...

Тогда я поставил дополнение для файрфокса MediaPlayerConnectivity и с его помощью получил адрес самого потока: 86.38.0.225:81. По закону подлости ни vlc, ни mplayer, ни уж тем более totem, проиграть этот поток не смогли :( Тогда, после долгого гугления я наткнулся на следующий рецепт:

mplayer mmshttp://86.38.0.225:81 # просто играет поток
mplayer -dumpstream mmshttp://86.38.0.225:81 -dumpfile asdf.avi # сохраняет поток в файл

Баг на launchpad: Ubuntu can't handle mmsh: streams.

суббота, 23 мая 2009 г.

Hamachi для Ubuntu

Hamachi — это такой инструмент, который позволяет соединять компьютеры в виртуальную сеть даже если у них нет выделенных ip-адресов.
С помощью checkinstall я сделал пакет для ubuntu: скачать.

Для работы надо выполнить следующие команды у клиентов и сервера:
# tuncfg
$ hamachi start

На сервере создаём сеть:
$ hamachi create mynetwork passwd # mynetwork — это название сети

Клиентами подключаемся:
$ hamachi join mynetwork

Узнаём выданные ip-адреса:
$ hamachi list
* [test23456]
46.45.44.190
[mynetwork]

Теперь можно использовать например удалённый рабочий стол. Система → Параметры → Удалённый рабочий стол. Тут включаем доступ к рабочему столу.
Приложения → Интернет → Просмотр рабочих столов. Тут указываем ip сервера из hamachi и подключаемся к нему.

Главное не забыть разрешить доступ по порту 5900 в файрволе.