Проксируем IPTV в HTTP

Для тех зашел сюда в поисках халявного IPTV сразу даю ссылку на свой плейлист, — смотрите на здоровье. Для успешного просмотра у вас должен быть открыт 4022 порт на хост berezhinskiy.name Трансляция ограничена 6ю смотрящими одновременно.

Для остальных — маленькое HOWTO на тему проксирования UDP multicast по протоколу HTTP:
Решение реализуется с помощью udpxy и 2х строк в rc.conf. Для начала проверим активирована ли поддержка мультикаст на интерфейсе:

# ifconfig net0 | grep MULTICAST
net0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500

Ставим udpxy:

# cd /usr/ports/net/udpxy/ && make install clean

Добавляем в rc.conf флаги запуска, стартуем и проверяем что порт слушается:

# cat /etc/rc.conf | grep udpxy
udpxy_enable="YES"
udpxy_flags="-m net0 -p 4022 -S -c 6"
# /usr/local/etc/rc.d/udpxy start
Starting udpxy.
# sockstat | grep udpxy
root     udpxy      56048 5  tcp4   *:4022                *:*

Флаги запуска:
* -m — имя интерфейса мультикаст-каналов
* -p — TCP порт для HTTP запросов к приложению
* -c — максимальное количество клиентов, обслуживаемых одновременно
* -l — записывать журнал приложения в указанный файл
* -S — передавать статистику о клиентских соединениях
Далее берем плейлист, который нам дал провайдер и изменяем под наши нужды:

# head tv_all.m3u
#EXTM3U
#EXTINF:0,1 - Channel 5 (Ukraine)
udp://@239.100.0.1:5004
#EXTINF:0,2 - 1+1 international (H264)
udp://@239.100.0.10:5004
#EXTINF:0,3 - UR1
udp://@239.100.0.101:5004
#EXTINF:0,4 - RADIO ERA
udp://@239.100.0.102:5004
#EXTINF:0,5 - L.Radio
# cat tv_all.m3u | sed -e 's@udp://\@@http://berezhinskiy.name:4022/udp/@' > TV.m3u

Естественно, заменяем http://berezhinskiy.name:4022 на свои ip:port, запускаем VLC/winamp/wmp и проверяем работоспособность. Если что не фурычит — смотрим лог и гуглим :)
Если вы оставили опцию -S в флагах запуска, — статистика будет доступна по адресу http://ip:port/status

Опубликовано 10.12.2011 в 18:16 · Автор Berezhinskiy · Ссылка · Комментариев нет
Рубрики: FreeBSD · Теги: , , , , ,

Бесплатный ssh доступ

Обнаружилось что ресурсы моего домашнего сервера почти не используются.
По этому решил сделать добро другим – бесплатно отдаю ssh к машине. Знаю, что многим ITшникам это может принести пользу если нужно что-то протестировать, подглядеть конфиг уже готового сервиса etc. Что уж говорить про анлимный канал и пробросы портов :)
По этой ссылке можно узнать подробности и оформить запрос.

Опубликовано 10.12.2011 в 15:07 · Автор Berezhinskiy · Ссылка · Комментариев нет
Рубрики: FreeBSD, Полезности · Теги: , ,

Пишем daemon на Python

Нужно было написать демона для одного проекта. Чтобы себе на будущее жизнь облегчить — написал модуль. Возможно еще кому-нибудь понадобится.
Копируем код, приведенный ниже и сохраняем под именем daemon.py

# -*- coding: utf8 -*-

__author__    = "Yaroslav Berezhinskiy"
__copyright__ = "Copyright (C) 2011 Yaroslav Berezhinskiy"

import os
import atexit
import sys
import time
from signal import SIGTERM 

#===========================================================================
# "Итерация свойственна человеку, рекурсия божественна."
# Видно, у Б-га стек длинный. А мы останемся людьми.
#===========================================================================

class Daemon():
    pidfile = 'pidfile.pid'
    stdin='/dev/null'
    stdout='/dev/null'

    def daemonize(self):
        pid = os.fork()
        if pid == 0:
            os.setsid()
            pid = os.fork()
            if pid == 0:
                os.chdir(".")
                os.umask(0)
            else:
                sys.exit(0)
        else:
            sys.exit(0)

        atexit.register(self.delpid)

        pid = str(os.getpid())
        file(self.pidfile,'w+').write("%s\n" % pid)
        return pid

    def descriptors(self):
        sys.stdout.flush()
        sys.stderr.flush()
        si = file(self.stdin, 'r')
        so = file(self.stdout, 'a+')
        os.dup2(si.fileno(), sys.stdin.fileno())
        os.dup2(so.fileno(), sys.stdout.fileno())

    def delpid(self):
        os.remove(self.pidfile)

    def start(self,interactive=False):
        if interactive:
            print "Starting program in interactive mode"
            self.run()
            return

        try:
            pf = file(self.pidfile,'r')
            pid = int(pf.read().strip())
            pf.close()
        except IOError:
            pid = None

        if pid:
            message = "Daemon already running? (pid=%s)\n"
            sys.stderr.write(message % pid)
            sys.exit(1)

        pid = self.daemonize()
        print "Starting daemon."
        self.descriptors()
        self.run()

    def stop(self):
        try:
            pf = file(self.pidfile,'r')
            pid = int(pf.read().strip())
            pf.close()
        except IOError:
            pid = None

        if not pid:
            message = "Daemon not running? (check %s)\n"
            sys.stderr.write(message % self.pidfile)
            return

        print "Stopping daemon.\nWaiting for PID: %s" % pid
        try:
            while 1:
                os.kill(pid, SIGTERM)
                time.sleep(0.1)
        except OSError, err:
            err = str(err)
            if err.find("No such process") > 0:
                if os.path.exists(self.pidfile):
                    os.remove(self.pidfile)
            else:
                print str(err)
                sys.exit(1)

    def restart(self):
        self.stop()
        self.start()

    def run(self):
        print >> sys.stderr, "ERROR: Daemon not started\nYou need to override run() method in your subclass!"
        sys.exit(1)

Дальше нам нужно подключить модуль, написать подкласс для Daemon() и переопределить в нем метод run().
Пример рабочего кода:

#!/usr/bin/env python
# -*- coding: utf8 -*-

import sys
import time
import daemon

class MyDaemon(daemon.Daemon):
    def __init__(self):
        #---------------------------- Override default PID file in Daemon() class
        daemon.Daemon.pidfile = "my_pidfile.pid"

    def run(self):
        while 1:
            time.sleep(1)

my_daemon = MyDaemon()

if len(sys.argv) >= 2:
    if 'start' == sys.argv[1]:
        my_daemon.start()
    elif 'stop' == sys.argv[1]:
        my_daemon.stop()
    elif 'restart' == sys.argv[1]:
        my_daemon.restart()
    else:
        print "Unknown command"
        sys.exit(2)
    sys.exit(0)

PROFIT

Также есть поддержка работы в интерактивном режиме. При передаче значения interactive=True в метод start(), модуль не будет форкать процесс и уводить его в фон, что может быть весьма полезно при отладке кода:

        my_daemon.start(interactive=True)
Опубликовано 16.10.2011 в 19:45 · Автор Berezhinskiy · Ссылка · Один комментарий
Рубрики: Programming, python · Теги: , , ,

Поиск parent/child PIDов по имени процесса

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

#!/bin/bash

getPID() {
    pids=( )
    par_pids=(`ps -ef | grep $1 | grep -v grep | awk '{print $3}' | xargs`)
    real_pids=(`ps -ef | grep $1 | grep -v grep | awk '{print $2}' | xargs`)

    if [[ ${#real_pids[*]} -eq 1 ]]; then
        if [[ $2 = "parent" ]]; then
            pids=(${real_pids[@]})
        elif [[ $2 = "child" ]]; then
            # No such child for $1 process
            pids=( 0 )
            return 1
        fi
    else
        for (( i = 0; i < ${#par_pids[*]}; i++ ))
        do
            for (( z = 0; z < ${#real_pids[*]}; z++ ))
            do
                if [[ ${par_pids[$i]} = ${real_pids[$z]} ]]; then
                    if [[ $2 = "parent" ]]; then
                        pids=(${pids[@]} ${par_pids[$i]})
                    elif [[ $2 = "child" ]]; then
                        pids=(${pids[@]} ${real_pids[$i]})
                    fi
                fi
            done
        done
    fi

    pids=(`echo ${pids[@]} | tr " " "\n" | sort -u | xargs`)
    return 0
}

getPID chrome parent
echo "Parents: ${pids[@]}"
getPID chrome child
echo "Childs: ${pids[@]}"

Вывод скрипта на моей бубунте для браузера Chrome:

$ ./get_pid.sh
Parents: 19212 19217
Childs: 19215 19238 19240 19244 19246 19250 19254 19258 19261 19264 19267 19273 19276 19281 19301 19334 19339 19346 19351 19367 19404
Опубликовано 23.03.2011 в 22:58 · Автор Berezhinskiy · Ссылка · Комментариев нет
Рубрики: bash, Linux, Programming, Полезности · Теги: , , ,

Подсчет среднего значения с помощю AWK

По работе я часто имею дело дело с логами эпических размеров, в которых указано значение «Total execution time». Для подсчета среднего/минимального/максимального времени выполнения, удобно использовать awk:

awk 'BEGIN{all=0;count=0;max=0;min=1000;} {input=int($1);all=all+input;++count;if (min>=input && input!=0){min=input}; if (input>=max){max=input};}END{print all/count " " min " " max}'

Пример вывода команды для подсчета размера возвращаемого обьекта в логах апача:

$ egrep "\s+200\s+" access.log.1 | awk 'BEGIN{all=0;count=0;max=0;min=1000;} {input=int($10);all=all+input;++count;if (min>=input && input!=0){min=input}; if (input>=max){max=input};}END{print all/count " " min " " max}'
794.36 152 2150
Опубликовано 20.02.2011 в 10:14 · Автор Berezhinskiy · Ссылка · Комментариев нет
Рубрики: Linux, Programming, Полезности · Теги: ,

Сказы Леса — Еблан

Имхо, это гениально…

Опубликовано 14.02.2011 в 12:22 · Автор Berezhinskiy · Ссылка · Комментариев нет
Рубрики: Музыка, Разное, Юмор · Теги: , ,

Шифрование дисков в FreeBSD

Для достижения нашей цели мы будем использовать GEOM класс доступный с FreeBSD версии 6.0 — GELI. Из достоинств:

Приступим. Собираем ядро со следующими опциями:

options         GEOM_ELI
device          crypto

Если не хотим собирать ядро — подгружем модулем и добавляем в /boot/loader.conf

# kldload geom_eli
# echo "geom_eli_load=\"YES\"" >> /boot/loader.conf

Отмонтируем будущий крипто-раздел, НЕ забыв сбэкапить все данные, ибо нам прийдется их уничтожить.
Читать полностью »

Опубликовано 03.02.2010 в 16:23 · Автор Berezhinskiy · Ссылка · 3 комментария
Рубрики: bash, FreeBSD, Security · Теги: , , ,

Реклама BSOD

Сегодня был на станции метро Святошин, видать с запуском рекламы Windows 7 на айбоксах начали рекламировать BSODы :)
bsod_ibox

Опубликовано 24.01.2010 в 19:13 · Автор Berezhinskiy · Ссылка · Комментариев нет
Рубрики: Юмор · Теги: , , ,

Контролируем провайдера

Всем сомнивающимся в количестве предоставляемых интернет-услуг, посвящается :)

Я живу в Киеве, пользуюсь услугами провайдера Corbina Telecom (не путайте с Русской Corbin’ой), чем вполне доволен. За 20$ в месяц я имею неплохой канал шириной 100Mbit по «Украине» и 25Mbit в «мир». Есть у меня балконная домашняя зверушка, которая шуршит кулерами и работает в режиме 24/7. Используется для разных полезных и не очень целей: гейт для локалки, прокся, впн, файлопомойка, хостинг (в том числе хостит MyJournal.org.ua) etc. Заморочился я как-то вопросом статистики аптайма моего канала. Вот что с этого вышло:
Читать полностью »

Опубликовано 12.01.2010 в 14:10 · Автор Berezhinskiy · Ссылка · 2 комментария
Рубрики: bash, FreeBSD, Programming · Теги: , , , , ,

FreeBSD Kernel NAT

Купил я себе новый HDD: WD GreenPower, емкостью 1 TB. Цель покупки — файло/медиапомойка. Организация любой помойки, при условии анлимного канала и аккаунта на torrents.ru — дело пустяковое. Через некоторое время активного использования торента (больше 20 раздач со скоростью > 1 Mb) начал замечать такую картину:

# top | grep natd
42549 root          1  45    0  9408K  2856K select   0:01  7.78% natd

Мало того, что natd светит адреса внутренних хостов, так он еще нехило потребляет системные ресурсы. Решено было переходить на «ядерный» нат. Добавляем в конфиг ядра опции для поддержки ipfw и ipfw nat:

options         IPFIREWALL
options         IPFIREWALL_FORWARD
options         IPFIREWALL_VERBOSE
options         IPFIREWALL_VERBOSE_LIMIT=1000
options         IPFIREWALL_NAT
options         LIBALIAS
options         IPDIVERT
options         DUMMYNET

Далее:

# cd /usr/src
# make buildkernel KERNCONF=NEW_MY_CONF
....
# make installkernel KERNCONF=NEW_MY_CONF

Ребутимся и редактируем скрипт ipfw. Коментим те строки, где были правила divert и заменяем на правила ipfw nat:
Читать полностью »

Опубликовано 09.11.2009 в 22:02 · Автор Berezhinskiy · Ссылка · 3 комментария
Рубрики: FreeBSD, Security · Теги: , , , , ,

Инсталляция FreeBSD с USB flash

Интернет кишит сложными подходами и зачастую не понятными реализациями этих простых действий. Я попытаюсь в разы упростить процесс создания загрузочного диска и инсталляции ОС в отсутствии CD драйва. После, мы напишем небольшой скрипт для автоматизации этого не хитрого процесса. Приступим.
Моя флешка определяется у меня как da0
Будте внимательны с именами устройств, так как у Вас есть отличная возможность затереть нужный системный раздел.
Создаем новый слайс, используя полный объем флешки:

# fdisk -I /dev/da0

Создаем label для размеченного раздела:

# bsdlabel -w -B /dev/da0s1

Форматируем раздел:

# newfs -f 8192 -b 65536 -U -o time /dev/da0s1a

Монтируем созданный раздел в каталог /mnt

# mount /dev/da0s1a /mnt

Теперь нам нужно скопировать содержимое образа FreeBSD на нашу флешку и отмонтировать накопитель. Для этих целей я использую DVD образ с сайта freebsd.org
Читать полностью »

ArpGuard

Теория

Вот что говорит нам о протоколе ARP педивикия:

ARP (англ. Address Resolution Protocol — протокол разрешения адресов) — протокол канального уровня (англ. Data Link layer), предназначенный для преобразования IP-адресов (адресов сетевого уровня) в MAC-адреса (адреса канального уровня) в сетях TCP/IP.

Более простыми словами можно сказать что ARP отвечает за соответствие пары IP-MAC.  ARP данные образуют кеш (таблицу) примерно такого вида:

(84.234.56.5) at 00:e0:4c:7e:e1:0c on net0
(192.168.0.1) at 00:e0:4c:5a:dd:e6 on lan0
(192.168.0.10) at 00:1c:bf:c6:b1:b7 on lan0

Таблица может быть динамической или статической. В случае динамического ARP-кеша, новые пары добавляются в него автоматически, путем ответа на широковещательный ARP-запрос. В противном случае на широковещательный запрос ответ не генерируется, а записи в таблицу нужно вносить руками. Чем нам может быть полезна статическая таблица?

Читать полностью »

Опубликовано 03.11.2009 в 19:27 · Автор Berezhinskiy · Ссылка · Комментариев нет
Рубрики: FreeBSD, Programming · Теги: , , ,

Монтирование ISO в FreeBSD

Все довольно тривиально:
Создаем виртуальный диск с нашей iso’шкой (md0), после чего монтируем его в нужную папку

# mdconfig -a -t vnode -f filename.iso -n 0
# mount_cd9660 /dev/md0 /path/to/folder

Соответственно размонтировать и уничтожить диск можно так:

# umount /path/to/folder
# mdconfig -d -u 0

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

#!/bin/sh

file_name="$2"
folder="$3"
mdcnf=/sbin/mdconfig
mntcd=/sbin/mount_cd9660
umnt=/sbin/umount

# Скрипт монтирования ISO
case "$1" in
        start)
                ${mdcnf} -a -t vnode -f ${file_name} -n 0
                ${mntcd} /dev/md0 ${folder}
                echo "ISO mounted"
                ;;
        stop)
                ${umnt} ${folder}
                ${mdcnf} -d -u 0
                echo "ISO umounted"
                ;;
        *)
                exit 64
                ;;
esac

Запуск и остановка:

# ./mnt_iso.sh start Leo4All.iso /mnt
ISO mounted
# ./mnt_iso.sh stop /mnt
ISO umounted
#
Опубликовано 25.08.2009 в 16:19 · Автор Berezhinskiy · Ссылка · Комментариев нет
Рубрики: FreeBSD, Programming · Теги: , , ,

Маша Badda Boo

Редкое сочетание красоты и таланта. Маша на livejournal.

Опубликовано 16.08.2009 в 22:43 · Автор Berezhinskiy · Ссылка · 3 комментария
Рубрики: Музыка · Теги: , ,

KyivBSD ’09

Собратья по консоли — объединяйтесь!  26 Сентября в столице Украины пройдет первая FreeBSD/PcBSD однодневная конференция. Участие в конференции планируется бесплатное, что не может не радовать. Все остальные подробности на сайте проекта.

Опубликовано 02.08.2009 в 14:26 · Автор Berezhinskiy · Ссылка · Комментариев нет
Рубрики: FreeBSD · Теги: , ,