Настройка параметров сети, а также authorized_keys root-а через параметры передаваемые ядру

Предлагаю добавить в на уровне Runlevel: boot в загрузку нечто вроде следующего скрипта

<code>
for p in `cat /proc/cmdline `;do
    if [ "$p" != "${p#authorized_keys=}" ]; then
        echo "ssh-rsa ${p#authorized_keys=} root@$(hostname)" >>/root/.ssh/authorized_keys
        /etc/init.d/sshd status || /etc/init.d/sshd start 
         # rc-update add sshd default &>/dev/null ## или этот вариант вместо предидущего если загрузка из Runlevel: boot
        rc-update del local &>/dev/null 
    fi
done</code>

здесь я предполагаю что при загрузке ядру пердан параметр authorized_keys= , а также что IP получается по DHCP

получаем удобный инструмент для удаленной установки/восстановления_после_краха системы. в случае с загрузочной флешкой, допустим так http://www.calculate-linux.ru/boards/20/topics/1749 или загрузки по PXE, добавить параметр к ядру ничего не стоит, можно даже использовать доп. параметр “nolocal” чтоб отключать службу local лишь по необходимости.

Вбивать открытый ключ не совсем удобное занятие. Куда проще его скопировать в /root и выполнить calculate --rebuild. Потом не забывайте, что для восстановления системы есть второй загрузочный раздел.

для одного ключа может и проще. но я еще хочу прикрутить задание IP в параметрах ядру, оно левые параметры все равно не обрабатывает.

А вещь эта полезная. к примеру(пример из жизни) есть у меня машины с уже установленной gentoo к которым физического доступа нет или он очень затруднен(вроде как встраиваемых систем разбросанных в оборудовании по городу). Зато у этих машин есть внешний IP, прописанный статически(у провайдера там всякие vlan-ы на свичах и прокинуть туда UDP:53 короче никак).

Установка кальки из оверлея на генту - не самый лучший вариант, долго и надо ничего не упустить, иначе можно после ребута туда непопась(есть опыт, хорошо что на машина в офисе была:). тем более у меня разбивка диска совершенно не подходит для кальки. так что я могу установить туда кальку лишь загрузившись с liveCD. но сидюка там нет и поставить никак.

Подитожим.
у меня есть:

  • несколько компов доступ к которым ограничен
  • IP на них задается статически, но IP - реальный
  • сильное желание перевести эти компы на кальку(не горит, но будет не лишним)

что мне надо

  • liveCD, а по сути с него лишь файл образа(livecd.squashfs), ядра(boot/vmlinuz) и initrd(boot/initrd), ну и livecd, а уж их я кину в /home(само собой отдельная партиция) и пропишу в grub
  • чтоб этот liveCD чудесным образом получил определенный статический IP
  • чтоб он позволил мне И ТОЛЬКО МНЕ попасть на эту загруженную систему

для выполнения последней задачи достаточно интегрировать authorized_keys прямо в livecd.squashfs и запустить sshd. но со статическим IP дело сложнее. не перепаковвывать же для этого образ с конфигом для каждой машины

и если сделать парсер /proc/cmdline настраивающий сеть - то к нему уже не будет лишним прикрутить заполнение /root/.ssh/authorized_keys

над этим парсером я сейчас работаю. по сути осталось продумать как лучше настраивать сеть, самый простой вариант через ifconfig не катит, есть возможность что демон настройки сети перебьет этиу настройку(к примеру ifplugd так и поступает)

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

Для подобных вещей в Calculate Linux есть шаблоны.

Разбейте задачу на две: обработка cmdline и модификация системы.

Для извлечения информации из cmdline, Вы можете создать свой профиль сборки, который будет состоять из двух файлов - скрипта загрузки подобно /etc/init.d/calculate с символической ссылкой в /etc/runlevels/boot/calculate. Скрипт загрузки извлечет IP из строки параметров ядра и пропишет его в файл профиля загрузки.

Во время загрузки livecd выполняется наложение профиля. Вы можете создать свой шаблон, который будет выполнять настройки. В нем будет Ваш открытый ключ для управления livecd, файл настройки сети и все остальные изменения.

предварительный вариант парсера готов, прошу критики, за профили пока не брался

<code>
#!/usr/bin/python
 # coding: utf-8

'''Читает из /proc/cmdline параметры определяющие настройку сети, а также задающие public ключи для sshd
    dsapub=<DSA-PUBLIC-KEY> rsapub=<RSA-PUBLIC-KEY> заносит их в /root/.ssh/authorized_keys
    rename_<MAC>=<ETH_NAME>     переименоввывает интерфейс с заданным MAC-address в <ETH_NAME>, сдесь и далее <MAC>==([0-9a-f]{12,12})
        (чтоб небыло путаницы когда несколько интерфейсов) пока что недоделал
    routes_<ETH_NAME>=(deafult|<NET_ADDRESS>):<IP_ADDRESS>      (deafult|<NET_ADDRESS>) via <IP_ADDRESS>
    config_<ETH_NAME>=IP.AD.DR.ES/NETMASK|null|noop|dhcp
    mac_<ETH_NAME>=<MAC>'''
from re import match
from os.path import dirname
from os import makedirs, chmod, symlink
from subprocess import Popen

AK_PATH='/root/.ssh/authorized_keys'
NET_PATH='/etc/conf.d/net'
CMDLINE='/proc/cmdline'

## это на время проверки
AK_PATH='/tmp/root/.ssh/authorized_keys'
NET_PATH='/tmp/net'
CMDLINE='./cmdline'

params=[ p.split('=',1) for p in open(CMDLINE).readline().split()]

def get_keys():
    '''Возвращает список строк готовых для записи в authorized_keys'''
    return ['dsapub'==p[0] and 'ssh-dss %s root@localhost\n'%p[1] or 'ssh-rsa %s root@localhost\n'%p[1] 
                for p in params if 2==len(p) and p[0] in ['dsapub','rsapub']]

def dossh():
    '''Если список возвращаемый get_keys() не пуст - пишет его и добавляет sshd в default '''
    authorized_keys=get_keys()
    if not authorized_keys: return
    try:    makedirs(dirname(AK_PATH),0o700)
    except: pass
    try:
        open(AK_PATH,'a').writelines(authorized_keys)
        chmod(AK_PATH,0o600)
    except: pass
    Popen('/sbin/rc-update add sshd default', shell=True)

def get_net_setups():
    confnet={}
    P={ '32':'([12]?\d|3[0-2])',
        'mac':'([0-9a-fA-F]){12,12}',
        'ip':'(1?\d{1,2}|2[0-4]\d|25[0-5])\.(1?\d{1,2}|2[0-4]\d|25[0-5])\.(1?\d{1,2}|2[0-4]\d|25[0-5])\.(1?\d{1,2}|2[0-4]\d|25[0-5])',
        }## patterns
    for p in params:
        if match('routes_eth\d',p[0]) and match('^(default|%(ip)s/%(32)s):%(ip)s$'%P, p[1]):
            confnet[p[0]]=confnet.pop(p[0],' ') + '    %s via %s\n'%tuple(p[1].split(':'))
        elif match('config_eth\d', p[0]) and match('^(%(ip)s(/%(32)s)?|null|noop|dhcp)$'%P, p[1]):
            confnet[p[0]]=confnet.pop(p[0],' ')+p[1]+' '
        elif match('mac_eth\d', p[0]) and match('^(%(mac)s)$'%P, p[1]):
            confnet[p[0]]=p[1]
    return confnet

def donet():
    '''Настривает /etc/conf.d/net и добавляет в default использованные интерфейсы'''
    try: open(NET_PATH,'a').writelines(['%s="%s"\n'%(p[0],p[1].strip()) for p in get_net_setups().items()])
    except: pass
    for h in reduce(lambda rslt,x: x not in rslt and rslt+[x] or rslt, [x.split('_',1)[1] for x in list(get_net_setups())], []):
        try:
            symlink('net.lo','/etc/init.d/net.%s'%h)
            Popen('/sbin/rc-update add net.%s default'%h, shell=True)
        except: pass

</code>

при тестировании использовал следующий файл

<code># cat ./cmdline
root=/dev/sda7 vga=791 resume=/dev/sda5 init=/sbin/bootchartd dsapub=AAAAB3NzaC1kc3MAAACBAJQVT8eez5PBUb8zN3NRg1V3SLJtnNQKkhfWpwZzs3aW6qN1t1okYY7xeoYNzBRt/pRXM2F44dSbSAjZTg1hvhgJxamsn4X3pQ/1rQED+GOxI10pK9vQVs3KmRGWTI8KODsgNuHt3DtOb48KhxLkDg+gnEGihHcNxcsZcEhFnxIfAAAAFQDwzclkU+UitdjLds3/5FItiyhx6wAAAIBE/83WwJzQrTKwGGjKg4eppPU9hplOHQvCp6dLFpf9UybW/fXAiMHMg4awnSyer6weuYCNYGtUFElpMFxwAQVghMamC9A+AQ5ff7var1bHKuqjoH1a7RZRx9HojIe7U+dvU4phk/3wSYDbBH5J2gISnj9DshcFlR5z1A9mIWagMQAAAIEAhf7VbEgbUUO0peCk3Ndt7TxbZlyGZqkBE7W//5XUuz9//Z4GtXZufDGm2DyrcIiSSw6rAYSPDSO8W6U4YxxwE4/EvCTkSEVpJgK0ocEdrfyscuMio/IEnljZ9s526SgBl5//0ctaGmcPnqNIY7EzcI3bp6g1/9qE3hv1P3aoYS0= rsapub=AAAAB3NzaC1yc2EAAAABIwAAAQEArlnMPGG3+fCDO4ctoy+VtxKPHB5XBFY/CP8KYIUC2ih3vD60AYOacmQiE440gRD1GV5FrEBrxfHBhXmn22ss11iw6VZ1i7cThNvgoystQfBf9owVJFvdE30pxA5NL6+apf/iOd5enI5Usmqc8tjNQISNJxhk/OeVTVdY7H+6YSdGw81K+tGRGSGa2Wh3ayRzcBb82Vl8q56Ipu848mhe15EfyrmIIre6CFEn+CqjzKLY5IbapXyxPiXoB5jArAnk3e0Brlgbas0wRDmvq3kE1615YYRBICyCMQBd/HeFPEZyiLWlPoSUp2Pbt4pIahk5HPKjomUjX2QnVoSF9YIuTw== mac_eth0=112233445566 config_eth0=192.168.2.3/24 config_eth0=10.11.12.13/8 routes_eth0=default:192.168.0.1 routes_eth0=172.16.0.0/16:10.10.10.1
</code>

соответственно параметры:

  • dsapub=AAAAB… - dsa-public-key
  • rsapub=AAAAB3N… - rsa-public-key
  • mac_eth0=112233445566 - как и в /etc/conf.d/net - новый mac-аддрес (а вдруг надо)
  • config_eth0=192.168.2.3/24 - как и в /etc/conf.d/net
  • config_eth0=10.11.12.13/8 - второй IP, соответственно добавляется
  • routes_eth0=default:192.168.0.1 - как и выше
  • routes_eth0=172.16.0.0/16:10.10.10.1 - как и выше

здесь в параметре routes что:через_кого разделяю знаком :
ничего умнее придумать не смог, поскольку и остальные подпараметры ядра разделяются этим знаком
в принципе можно былоб сюда еще привязать Bonding и кучу других параметров, но все это можно сделать и с запущенной системы, главное на неее попасть.

rename_=<ETH_NAME> задумал, чтоб можно было явно указать какой интерфейс как называть, имеет смысл если есть несколько интерфейсов и неясно какой ядро определит первым, править скриптом /etc/udev/rules.d/70-persistent-net.rules до запуска /etc/init.d/udev нехочу, ибо некошерно это.
если кто знает как/чем заставить udev переименовать интерфейс - буду благодарен за подсказку.

в принципе dsapub,rsapub по идее можно былоб и проверять на наличие этих ключей в authorized_keys, но я же предполагаю, что этот скрипт используется лишь в LiveCD, ибо он слишком опасен если grub незапоролен

приму советы настройку еще чего стоит включить, для обеспечения дистанционного доступа к системе через параметры ядра