Необходимо собрать свитч из стандартного ПК.
На машине имеется 2 встроенные сетевые Реалтэк,
и 4-х портовая плата PCI-X Intel (итого 6 портов).
Задачи свича:
а) Мултикаст роутер.
б) Необходимо иметь возможность дропать определенные категории пакетов на определенных интерфейсах.
1. Собираю минимальную ФС
1.1 Устанавливаю по дефолту Astra-linux-orel-1.9
1.2 Создаю каталог где будет собираться образ будущей системы и перехожу в него:
mkdir -p /root/src
cd /root/src
1.3 Перед сборкой файловой системы, необходимо смэйковать busybox:
mkdir busybox
cd busybox
wget ftp://astra-linux.com/astra/stable/orel/1.9/repository/pool/main/b/busybox/busybox_1.20.0.orig.tar.bz2
tar -xjf busybox_1.20.0.orig.tar.bz2
cd busybox-1.20.0
make menuconfig
##############################################################
General Configuration --->
Build Options --->
[*] Build Busybox as a static binary (no shared libs)
##############################################################
# Кроме статической компиляции выбираем нужные опции и мэйкуем
make
mkdir ../../switch_src
cp -a busybox ../../switch_src
cd ../..
1.4 Файловую систему буду собирать при помощи скрипта, поэтому создаю скрипт и делаю его исполняемым:
pwd /root/src
touch buildswitch
chmod +x buildswitch
1.5 Содержимое скрипта:
=========================================================================
#!/bin/bash
set -x
# Директория где будет собираться образ ФС
ROOTFS="/root/src/fs/switchfs"
# Директория где лежат необходимые файлы для сборки ФС (об этом ниже)
SRC="/root/src/switch_src"
mkdir -p $ROOTFS
cd $ROOTFS
rm -rf *
# MINIMAL_INSTALL
mkdir -p bin dev etc etc/init.d lib lib/x86_64-linux-gnu lib64 proc root sbin sys tmp usr/lib usr/lib/x86_64-linux-gnu usr/bin usr/sbin usr/share \
var/empty var/log var/run
chmod 1777 tmp
cd lib/x86_64-linux-gnu
cp /lib/x86_64-linux-gnu/ld-2.13.so .
cp /lib/x86_64-linux-gnu/libc-2.13.so .
cp /lib/x86_64-linux-gnu/libm-2.13.so .
cp /lib/x86_64-linux-gnu/libprocps.so.0.0.1 .
cp /lib/x86_64-linux-gnu/libnss_files-2.13.so .
cp /lib/x86_64-linux-gnu/libgcc_s.so.1 .
ln -s ld-2.13.so ld-linux-x86-64.so.2
ln -s libc-2.13.so libc.so.6
ln -s libm-2.13.so libm.so.6
ln -s libnss_files-2.13.so libnss_files.so.2
ln -s libprocps.so.0.0.1 libprocps.so.0
cd $ROOTFS/lib64
ln -s /lib/x86_64-linux-gnu/ld-2.13.so ld-linux-x86-64.so.2
# FSTAB
cd $ROOTFS
touch etc/fstab
echo "none /proc proc defaults 0 0" > etc/fstab
# INITTAB
touch etc/inittab
echo "::sysinit:/etc/init.d/rcS" > etc/inittab
echo "::once:-/bin/sh" >> etc/inittab
echo "::ctrlaltdel:/sbin/reboot" >> etc/inittab
echo "::shutdown:/bin/umount -a -r" >> etc/inittab
echo "::restart:/sbin/init" >> etc/inittab
echo "tty2::askfirst:-/bin/sh" >> etc/inittab
# RCS
touch etc/init.d/rcS
chmod +x etc/init.d/rcS
cat > etc/init.d/rcS << "EOF"
#!/bin/ash
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -o remount,rw /dev/ram0 /
mknod /dev/null c 1 3
mknod /dev/tty c 5 0
mdev -s
mkdir -p /dev/pts
mount -t devpts devpts /dev/pts
syslogd -O /var/log/messages
ifconfig lo 127.0.0.1 up
# Настройка сетевых интерфейсов перед добавлением в бридж
ip a a 0.0.0.0 dev eth0
ip a a 0.0.0.0 dev eth1
ip a a 0.0.0.0 dev eth2
ip a a 0.0.0.0 dev eth3
ip a a 0.0.0.0 dev eth4
ip a a 0.0.0.0 dev eth5
# Добавляю интерфейсы в бридж
brctl addbr br0
brctl addif br0 eth0
brctl addif br0 eth1
brctl addif br0 eth2
brctl addif br0 eth3
brctl addif br0 eth4
brctl addif br0 eth5
# Поднимаю интерфейсы
# На данном этапе возможны проблемы
# Дело в том, что в дефолтной Astra-linux железо инициализирует демон UDEV
# Система собранная мной, работает на основе BUSYBOX, в котором железо инициализирует демон MDEV (посути обрезанный UDEV)
# UDEV и MDEV по разному инициализируют железо
# В результате имена сетевых интерфейсов в дефолтной Astra-linux и в системе на основе BUSYBOX будут различатся
# Один и тот же интерфейс в дефолтной Astra-linux м.б. eth0, а в системе на основе BUSYBOX eth4
# В дефолтной Astra-linux имена сетевых интерфейсов можно изменить в файле /etc/udev/rules.d/70-persistent-net.rules
# В системе на основе BUSYBOX, можно поступить следующим образом (пример, необходимо редактировать в конкретном случае)
ip link set name eth6 dev eth0 # Сначала необходимо освободить имя eth0, поэтому переименовываю его в свободное (незанятое
# имя) например eth6
ip link set name eth0 dev eth1 # Затем переименовываю eth1 (или другой интерфей которому необходимо назначить имя eth0) в eth0
ip link set dev eth0 up # Поднимаю eth0
ip link set name eth1 dev eth2 # Переименовываю eth2 в eth1
ip link set dev eth1 up # Поднимаю eth1
ip link set name eth2 dev eth3 # Переименовываю eth3 в eth2
ip link set dev eth2 up # Поднимаю eth2
ip link set name eth3 dev eth4 # Переименовываю eth4 в eth3
ip link set dev eth3 up # Поднимаю eth3
ip link set name eth4 dev eth5 # Переименовываю eth5 в eth4
ip link set dev eth4 up # Поднимаю eth4
ip link set name eth5 dev eth6 # Остался последний интерфейс eth6 (который переименовали вначале eth0 -> eth6),
# переименовываю eth6 в eth5
ip link set dev eth5 up # Поднимаю eth5
# Назначаю IP-address и поднимаю бридж
ip a a 192.168.1.1/24 dev br0
ip link set dev br0 up
# На всякий случай
sleep 1
# Кладу в переменные пиды процессов сетевых карт
pid_eth0=`ps | grep -v grep | grep 'eth0' |awk '{print $1}'` > /dev/null 2>&1
pid_eth1=`ps | grep -v grep | grep 'eth1' |awk '{print $1}'` > /dev/null 2>&1
pid_eth2=`ps | grep -v grep | grep 'eth2' |awk '{print $1}'` > /dev/null 2>&1
pid_eth3=`ps | grep -v grep | grep 'eth3' |awk '{print $1}'` > /dev/null 2>&1
pid_eth4=`ps | grep -v grep | grep 'eth4' |awk '{print $1}'` > /dev/null 2>&1
pid_eth5=`ps | grep -v grep | grep 'eth5' |awk '{print $1}'` > /dev/null 2>&1
# По пидам выставляю сетевым интерфейсам максимальный приоритет ввода\вывода,
# максимальный приоритет доступа к ресурсам процессора,
# и привязываю сетевые интерфейсы к ядрам процессора, что бы исключить миграцию между ядрами (поскольку собирается реал-тайм
# система)
renice -20 -p $pid_eth0 && chrt -f -p 99 $pid_eth0 && taskset -p 1 $pid_eth0 > /dev/null 2>&1
renice -20 -p $pid_eth1 && chrt -f -p 99 $pid_eth1 && taskset -p 2 $pid_eth1 > /dev/null 2>&1
renice -20 -p $pid_eth2 && chrt -f -p 99 $pid_eth2 && taskset -p 3 $pid_eth2 > /dev/null 2>&1
renice -20 -p $pid_eth3 && chrt -f -p 99 $pid_eth3 && taskset -p 4 $pid_eth3 > /dev/null 2>&1
renice -20 -p $pid_eth4 && chrt -f -p 99 $pid_eth4 && taskset -p 1 $pid_eth3 > /dev/null 2>&1
renice -20 -p $pid_eth5 && chrt -f -p 99 $pid_eth5 && taskset -p 2 $pid_eth3 > /dev/null 2>&1
# Дропаю форвард броадкаста на интерфейсе eth1
# Необходимо запретить броадкаст от определенной машины (MAC 08:00:22:03:15:03) и только на определенном интерфейсе (eth1)
# Для этого в систему были добавленны iptables и ebtables (пока обхожусь ebtables)
/sbin/ebtables -A FORWARD -p IPv4 -s 08:00:22:03:15:03 -d FF:FF:FF:FF:FF:FF -o eth1 -j DROP
# Стартую телнет и синхронизирую время
telnetd -l /bin/login
hwclock -s
EOF
# GROUP
touch etc/group
echo "root:x:0:" > etc/group
echo "toor:x:500:" >> etc/group
# GSHADOW
touch etc/gshadow
echo "root:*::" > etc/gshadow
echo "toor:*::" >> etc/gshadow
# PASSWD
touch etc/passwd
echo "root:x:0:0:,,,:/:/bin/ash" > etc/passwd
echo "toor:x:500:500:,,,:/var/empty:" >> etc/passwd
# SHADOW
touch etc/shadow
echo "root::14000:0:99999:7:::" > etc/shadow
echo "toor::14000:0:99999:7:::" >> etc/shadow
# NSSWITCH.CONF
touch etc/nsswitch.conf
echo "passwd: files" > etc/nsswitch.conf
echo "shadow: files" >> etc/nsswitch.conf
echo "group: files" >> etc/nsswitch.conf
echo "hosts: dns" >> etc/nsswitch.conf
# BUSYBOX.CONF
touch etc/busybox.conf
echo "[SUID]" > etc/busybox.conf
echo "login = ssx root.root" >> etc/busybox.conf
# LOCALTIME
cp -a /etc/localtime etc/
# MTAB
cd etc
ln -s /proc/mounts mtab
cd $ROOTFS
# PROTOCOLS
cp -a /etc/protocols etc/
# ETHERTYPES
cp -a /etc/ethertypes etc/
# IPTABLES
cp -a /sbin/xtables-multi sbin/
cd sbin
ln -s xtables-multi iptables
cd $ROOTFS
cp -a /lib/libip4tc.so.0.0.0 lib/
cp -a /lib/libip6tc.so.0.0.0 lib/
cp -a /lib/libxtables.so.7.0.0 lib/
cd lib
ln -s libip4tc.so.0.0.0 libip4tc.so.0
ln -s libip6tc.so.0.0.0 libip6tc.so.0
ln -s libxtables.so.7.0.0 libxtables.so.7
cd $ROOTFS
# EBTABLES
# Ebtables по дефолту отсутствует в системе, поэтому перед запуском скрипта необходимо выполнить apt-get install ebtables
cp -a /sbin/ebtables sbin/
mkdir lib/ebtables
cp -a /lib/ebtables/* lib/ebtables/
# BUSYBOX
# В каталоге /root/src/switch_src (переменная $SRC) лежит смэйкованный busybox, копирую в каталог bin
cp -a $SRC/busybox bin/
# Инсталирую busybox, удаляю ссылку linuxrc, создаю ссылку init.
chroot . /bin/busybox --install -s
unlink linuxrc
ln -s /bin/busybox init
# # strip
strip -vs bin/*
strip -vs sbin/*
strip -vs usr/sbin/*
strip -vs usr/bin/*
strip -vs lib/x86_64-linux-gnu/*
strip -vs lib64/*
strip -vs usr/lib/*
strip -vs usr/lib/x86_64-linux-gnu/*
=========================================================================
1.6 Пакую образ ФС в initramfs.igz
find . | cpio -H newc -o | gzip -9 > /root/src/switch_src/initramfs.igz
1.7 Собираю ядро
mkdir /root/src/kernel
cd /root/src/kernel
wget ftp://astra-linux.com/astra/stable/orel/1.9/repository/pool/main/l/linux/linux_3.2.0.orig.tar.gz
wget https://www.kernel.org/pub/linux/kernel/projects/rt/3.2/older/patch-3.2-rt10.patch.bz2
tar xvzf linux_3.2.0.orig.tar.gz
bzip2 -d patch-3.2-rt10.patch.bz2
cd linux-3.2
patch -p1 < ../patch-3.2-rt10.patch
cp -a /root/src/switch_src/config .config # Был готовый конфиг
linux64 make menuconfig
# Опишу только необходимые опции данной конфигурации, скопированный выше конфиг содержит все необходимые опции
# минимального ядра
# Добавляю поддержку initramfs
General setup --->
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
() Initramfs source file(s)
[*] Support initial ramdisks compressed using gzip
[ ] Support initial ramdisks compressed using bzip2
[ ] Support initial ramdisks compressed using LZMA
[ ] Support initial ramdisks compressed using XZ
[ ] Support initial ramdisks compressed using LZO
# Модулей у меня нет поскольку ядро статик
[ ] Enable loadable module support --->
# Тип процессора
Processor type and features --->
Processor family (Generic-x86-64) ---> # Добавляю поддержку 64bit процессора
(X) Generic-x86-64
Preemption Model (Fully Preemptible Kernel (RT)) ---> # Полностью вытесняемое ядро (RT-Kernel)
(X) Fully Preemptible Kernel (RT)
Timer frequency (1000 HZ) ---> # Выставляю таймер на 1000 HZ
(X) 1000 HZ
# Поддержка сетевых функций
[*] Networking support --->
Networking options --->
[*] Packet socket
[*] Unix domain sockets
[*] TCP/IP networking
[*] IP: multicasting
[*] IP: kernel level autoconfiguration
[*] IP: DHCP support
[*] IP: multicast routing # Созданная система должна выполнять роль мультикаст роутера
[*] IP: PIM-SM version 1 support
[*] IP: PIM-SM version 2 support
[*] IP: ARP daemon support
[*] IP: TCP syncookie support
[*] Network packet filtering framework (Netfilter) --->
[*] Advanced netfilter configuration
[*] Bridged IP/ARP packets filtering # Необходимо дропать определенные пакеты на определенных портах
# поэтому мне необходим фильтр на бридже
Core Netfilter Configuration --->
-*- Netfilter NFQUEUE over NFNETLINK interface
-*- Netfilter LOG over NFNETLINK interface
[ ] Netfilter connection tracking support
-*- Netfilter Xtables support (required for ip_tables)
*** Xtables combined modules ***
-*- nfmark target and match support
*** Xtables targets ***
[*] AUDIT target support # Поскольку с iptables пришлось работать впервые (предпочитаю BSD и
# PF), а собираемая система была лишь тестовым образцом
[*] "CLASSIFY" target support # я не стал разбираться со значением опций, тупо выбрал все (авось не
# сломается).
[*] IDLETIMER target support # Впринципе iptables мне не нужен, добавил на всякий случай, если вдруг
# мне все же захочется каких-то особых извращений,
[*] "MARK" target support # что бы не пересобирать ядро снова.
[*] "NFLOG" target support
[*] "NFQUEUE" target Support
-*- "RATEEST" target support
[*] "TEE" - packet cloning to alternate destination
[*] "TCPMSS" target support
*** Xtables matches ***
[*] "addrtype" address type match support
[*] "comment" match support
[*] "cpu" match support
[*] "dccp" protocol match support
[*] "devgroup" match support
[*] "dscp" and "tos" match support
[*] "esp" match support
[*] "hashlimit" match support
[*] "hl" hoplimit/TTL match support
[*] "iprange" address range match support
[*] "length" match support
[*] "limit" match support
[*] "mac" address match support
[*] "mark" match support
[*] "multiport" Multiple port match support
[*] "osf" Passive OS fingerprint match
[*] "owner" match support
[*] "physdev" match support
[*] "pkttype" packet type match support
[*] "quota" match support
[*] "rateest" match support
[*] "realm" match support
[*] "recent" match support
[*] "sctp" protocol match support (EXPERIMENTAL)
[*] "statistic" match support
[*] "string" match support
[*] "tcpmss" match support
[*] "time" match support
[*] "u32" match support
IP: Netfilter Configuration --->
[*] IP Userspace queueing via NETLINK (OBSOLETE)
[*] IP tables support (required for filtering/masq/NAT)
[*] Packet filtering
[*] ARP tables support
[*] ARP packet filtering
[*] Ethernet Bridge tables (ebtables) support --->
--- Ethernet Bridge tables (ebtables) support # Здесь аналогичная ситуация как и с iptables, тупо выбрал все
[*] ebt: broute table support
[*] ebt: filter table support
[*] ebt: nat table support
[*] ebt: 802.3 filter support
[*] ebt: among filter support
[*] ebt: ARP filter support
[*] ebt: IP filter support
[*] ebt: limit match support
[*] ebt: mark filter support
[*] ebt: packet type filter support
[*] ebt: STP filter support
[*] ebt: 802.1Q VLAN filter support
[*] ebt: arp reply target support
[*] ebt: dnat target support
[*] ebt: mark target support
[*] ebt: redirect target support
[*] ebt: snat target support
[*] ebt: log support
[*] ebt: ulog support (OBSOLETE)
[*] ebt: nflog support
[*] 802.1d Ethernet Bridging
[*] IGMP/MLD snooping
-*- DNS Resolver support
Device Drivers --->
[*] Network device support --->
[*] Ethernet driver support ---> # На машине имеется 2 встроенные сетевые Realtek 8169
[*] Intel devices # и четырех портовая плата Intel в PCI-X
[*] Intel(R) PRO/1000 Gigabit Ethernet support # Выбираю необходимые драйвера
[*] Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support
[*] Realtek devices
[*] Realtek 8169 gigabit ethernet support
[*] Real Time Clock ---> # Необходимо для синхронизации времени
--- Real Time Clock
[*] Set system time from RTC on startup and resume (NEW)
(rtc0) RTC used to set the system time (NEW)
*** RTC interfaces ***
[*] /sys/class/rtc/rtcN (sysfs) (NEW)
[*] /proc/driver/rtc (procfs for rtc0) (NEW)
[*] /dev/rtcN (character devices) (NEW)
*** SPI RTC drivers ***
*** Platform RTC drivers ***
[*] PC-style 'CMOS' (NEW)
# Остальные опции выбираем по необходимости
# Мэйкую ядро
linux64 make -j3
# Копирую собранное ядро в каталог /root/src/switch_src
cp arch/x86/boot/bzimage /root/src/switch_src/vmlinuz-bridge
1.8 Система практически готова, осталось создать раздел, положить туда образ ФС initramfs.igz и ядро vmlinuz-bridge, и установить загрузчик.
# Предположим, что в машине имеется еще один диск
cfdisk /dev/sdb
/dev/sdb1 1024MB # Создаем раздел 1Gb
# Форматируем в ext2
mke2fs /dev/sdb1
tune2fs -c 0 -i 0 /dev/sdb1
# Монтируем в /mnt
mount /dev/sdb1 /mnt
# Копируем ядро и образ ФС системы
cp -a /root/src/switch_src/vmlinuz-bridge /mnt
cp -a /root/src/switch_src/initramfs.igz /mnt
# Гружусь с Gentoo LIVE CD
# Монтирую sdb1 в /mnt
mount /dev/sdb1 /mnt
# В /mnt создаю каталог grub
mkdir /mnt/grub
# Копирую в него необходимые грабовские файлы
cp /boot/grub/stage? /boot/grub/e2fs_stage1_5 /mnt/grub
# Отмонтирую раздел
umount /mnt
# Устанавливаю загрузчик
grub
grub> device (hd0) /dev/sdb
grub> root (hd0,0)
grub> setup (hd0)
grub> quit
# Создаю файл menu.lst
# Для этого снова монтирую раздел
mount /dev/sdb1 /mnt
touch /mnt/grub/menu.lst
echo "timeout 0" > /mnt/grub/menu.lst
echo "default 0" >> /mnt/grub/menu.lst
echo "fallback 2" >> /mnt/grub/menu.lst
echo "title Bridge" >> /mnt/grub/menu.lst
echo "kernel /vmlinuz-bridge initrd=/initramfs.igz quiet ramdisk_size=32768" >> /mnt/grub/menu.lst
echo "initrd /initramfs.igz" >> /mnt/grub/menu.lst
# Вот что должно получится
cat /mnt/target/grub/menu.lst
timeout 0
default 0
fallback 2
title Bridge
kernel /vmlinuz-bridge initrd=/initramfs.igz quiet ramdisk_size=32768
initrd /initramfs.igz
# Отмонтирую раздел
umount /mnt/target
# Загружаюсь в новой системе, проверяю работу.