кто стучится в дверь ко мне?
Интересные и прогрессивные идеи, как водится, буквально витают в воздухе и могут забрести в голову совершенно разным людям, живущим в удаленных друг от друга частях света. Вот почему, кстати, мне и не нравится идея патентования программного обеспечения – первый поймавший идею за хвост лишает тысячи других людей права пользоваться их собственными идеями.
Ну да мы отвлеклись... Я, собственно, вот к чему клоню: еще в конце 90-х ваша покорная слуга сотоварищи вовсю увлекалась обсуждением вещей, которые сейчас получили научное название «скрытые каналы передачи информации». Мы, тогда еще совсем юные сетевики, фантазировали, как можно использовать служебную информацию, содержащуюся в пакетах данных, для передачи некой высокоуровневой информации. И первое, что приходило в этой связи в голову – использовать последовательности пакетов с определенными характеристиками (в самом простом варианте это номер протокола, порт, установленные флаги) как своеобразные пароли или команды, с помощью которых можно общаться с удаленным хостом без установления соединений как в прямом (TCP), так и в переносном смысле слова (UDP хоть и является протоколом, не ориентированным на соединение, но все же требует от серверной стороны открытия UDP-порта). Однако никто из нас не отринул лень, дабы сесть написать пару сотен строк кода, реализующего эту не бог весть какую сложную идею. А вот Judd Vinet – известный разработчик свободного ПО из Британской Колумбии, автор дистрибутива Arch Linux – взял и написал свой knock, набор из сервера и клиента, реализующий вышеописанную идею. Полторы тысячи строк серверного кода плюс 167 строк клиентского приложения, которое, кстати, вообще опционально. Но не будем забегать вперед...
матчасть
Для начала расскажу, как это все хозяйство работает и для чего его можно использовать. Итак, серверная часть – knockd - сидит в системе и слушает проходящий по интерфейсам трафик, совсем как банальный сниффер. Инструментарий для захвата пакетов используется вполне стандартный – библиотека libpcap. Ее используют большинство юниксовых снифферов, она отлично написана, портабельна (работает на всех POSIX-совместимых ОС, под Windows тоже есть версия под названием WinPcap).
Заметив в потоке трафика определенную последовательность пакетов (описания таких последовательностей задает администратор системы в простеньком конфигурационном файле), knockd выполняет указанную в том же конфиге команду. Командой, как вы понимаете, может быть в данном контексте и одиночное действие, и здоровенный shell-script.
В качестве примера практического использования обычно приводят «случай с файрволлом и ssh». Вот, скажем, хотите вы максимально ограничить удаленный доступ к вашему серверу из внешних сетей. Полностью отказаться от того же ssh – идея на грани безумия/фантастики, мало ли что может случиться с удаленным хостом в наши времена... Можно с помощью файрволла разрешить доступ к ssh только с определенного адреса. Но опять же – если вы в командировке или на отдыхе за границей, сможете ли вы уверенно назвать IP-адреса того интернет-кафе, из которого вам придется работать? Вы возразите, что можно попросить кого-то прописать новый адрес на файрволле. Но если рядом с сервером кто-то есть, то почему бы ему не провести работы по его налаживанию самостоятельно, а? ;) Значит, имеем в виду, что рядом никого толкового может и не быть.
И вот тут knockd реально может помочь. Вы посылаете некую последовательность пакетов, и knockd командует файрволлу открыть для вашего текущего адреса доступ к порту ssh.
конкретика
Разберем ситуацию на примере. Допустим, есть следующие правила файрволла (в нашем примере это будет линуксовый netfilter/iptables):
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT tcp -- 192.168.0.100 0.0.0.0/0 tcp dpt:22
DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
То есть никому, кроме 192.168.0.100, на наш сервер на 22 порт TCP соваться нельзя.
Перед тем, как запустить knockd, пропишем ему в конфиг следующее:
[openSSH]
sequence = 7000,8000,9000
seq_timeout = 5
command = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn
[closeSSH]
sequence = 9000,8000,7000
seq_timeout = 5
command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn
Я думаю вам и без моих объяснений уже все понятно :) Но на всякий случай поясняю. Если knockd заметит последовательность из трех TCP-пакетов с выставленным флагом SYN (начало установления соединения) на порты 7000, 8000 и 9000 – добавит в начало списка правил файрволла строку, разрешающую адресу отправителя (то есть вашему текущему IP-адресу) соединяться с ssh. По завершении удаленной работы вы можете вернуть все, так сказать, на родину – последовательность аналогичных пакетов на порты 9000, 8000 и 7000 даст команду на удаление добавленного ранее правила. Доступ закрыт.
Еще раз хочу обратить ваше внимание на то, что руление вашим драгоценным файрволлом – не единственное возможное применение knockd. Мне показалось несколько курьезным, что в системе управления пакетами Gentoo Linux в списке зависимостей обнаружился iptables. Ну хорошо хоть, что эта зависимость числится там «желательной», а не обязательной. Но все равно народ смущает. Поэтому приведу свой собственный тестовый конфиг.
[hello world]
sequence = 60000,4000
seq_timeout = 30
command = echo “hello, world!” > /root/helloworld
tcpflags = syn
Как видите, последовательность можно взять произвольной длины, таймаут можно увеличить (потом станет понятно, зачем), а команда может делать что- то вовсе не связанное с файрволлом :)
Конечно же, это не все опции конфига. Во-первых, само собой разумеется, что можно сочетать в кодовой последовательности TCP- и UDP-пакеты. Можно указывать две команды – одна выполняется после получения кодовой последовательности, а другая по истечении некоторого таймаута... Подробнее все это описано в документации.
чем стучать*?
Чтобы послать нужную последовательность пакетов, мы можем воспользоваться самыми разнообразными инструментами. В стандартную поставку наряду с серверной частью входит и клиент под названием knock. Он умеет стучать по TCP и UDP, причем как всей пачкой (только TCP или только UDP), так и вразнобой. Плюсы использования этой утилиты очевидны: минимальные задержки между пакетами, интерфейс заточен именно под конкретную задачу. Есть и порт под Windows (Cygwin). Но есть минус: не везде вы сможете этой утилитой воспользоваться. Хорошо, если у вас ноутбук со всем необходимым софтом, а если придется работать из интернет-кафе? Или с чужой машины, где установка нового софта, пусть даже и такого мелкого, как knock, не приветствуется? Генераторы пакетов, утилиты типа hping, netcat, sendip в вашем распоряжении. Более того, если ваши кодовые последовательности не длинные, таймауты выставлены большие и используется только TCP, вы можете стучать всем, что попадется под руку – хоть telnet-ом, хоть браузером.
о безопасности
У скептиков, я думаю, уже накопилось много вопросов насчет безопасности такого решения. И первый вопрос, волнующий народ, я думаю, звучит так: «А что если последовательность будет подобрана или перехвачена?»
Насчет подбора – ну это философский вопрос :) Последовательность из произвольного (ну, скажем, так достаточно большого) количества пакетов, направленных на номера портов от 1 до 65535, выгодно отличается от пароля, в котором используется меньше вариантов составляющих (сложите буквы, цифры и символы, которые вы можете набрать с клавиатуры – сколько получается? ;)) Грамотный админ всегда отследит подбор пароля к сервисам, так почему подбор последовательности пакетов станет для него неожиданностью? ;)
С перехватом дела несколько хуже – действительно теоретически перехватить кодовую последовательность можно. Я говорю «теоретически», потому что хотелось бы мне взглянуть на психопата, просеивающего трафик в поисках неизвестно чего, разве что вы использовали стандартные последовательности из конфигов или слишком уж примечательные порты (ну вы же не будете так делать, правда? ;)
Но все же, поскольку теоретическую возможность перехвата мы признаем, взглянем на так сказать смягчающие обстоятельства.
Во-первых, вряд-ли вы будете использовать в качестве команды, запускаемой knockd, что-то вроде rm –rf / Маловероятно и то, что шпионы или террористы будут обсуждать с помощью такого скрытого канала свои страшные тайны. В общем, тут вопрос исключительно управления рисками – если риск небольшой, а удобство очевидно – пользуйтесь, да это касается не только knockd, но всех без исключения технических средств и технологий передачи данных, что я вам тут рассказываю...
Скорее всего большинство ограничатся описанной выше файрвольно-ssh-шной комбинацией. А у ssh есть свои вполне надежные методы авторизации и шифрования, файрволл просто добавляет второй рубеж защиты для особо параноидальных админов. Вот и будем это решение с такой точки зрения и рассматривать – дополнительный рубеж защиты, или достаточно наивное стеганографическое средство для не особо «тяжелых» случаев.
Во-вторых, для усиления защиты в knockd есть и штатное решение. Речь идет о так называемых одноразовых последовательностях. Эта штука напоминает кодовые карты, используемые для интернет-банкинга или для систем доступа в организациях с повышенными требованиями к безопасности. Идея проста – после каждого использования кодовая последовательность «сгорает», следующий раз она уже не сработает, нужно брать следующую по списку. Списки последовательностей для knockd представляют собой простые текстовые файлы, в каждой строке которого содержится одна последовательность в формате, аналогичном тому, что используется в директиве sequence конфигурационного файла. Подключение фичи одноразовых последовательностей происходит следующим образом:
one_time_sequences = /etc/knockd/smtp_sequences
где то, что после знака «=» - имя файла, содержащего список одноразовых последовательностей.
Стоит заметить, что клиентской программой эта фича как бы не поддерживается, то есть интерфейса для «скармливания» фалов кодовых
последовательностей у knock нет. Если этоих последовательностей немного и они не очень длинные, можно набивать их каждый раз вручную с некой электронной или бумажной шпаргалки на манер тех самых банковских кодовых карт. В противном случае вам придется написать некий «костыль» самостоятельно – unix way вам в помощь, господа.
послесловие
Я сознательно не стала описывать процедуру установки этого нехитрого софта, поскольку а) у каждого свои излюбленные методы добычи и установки пакетов (еще holy wars нам тут не хватало :) и б) эти бесконечные ./configure, make, make install ИМХО всех уже порядком достали. Да и, на мой взгляд, это разжевывание в некотором роде унижает продвинутых админов, коих, я полагаю, большинство среди читателей СР. Хотя две вещи все же скажу:
1. Сайт проекта доступен по адресу http://www.zeroflux.org/cgi-bin/cvstrac.cgi/knock/wiki.
2. Не забудьте удостовериться в наличии libpcap в вашей системе. При наличии отсутствия ;) – установите, Google вам в помощь.
За сим позвольте откланяться. И... Good knocking!
сноска
* knock по-английски, если кто не в курсе, означает «стук».
Alice D. Saemon
Ну да мы отвлеклись... Я, собственно, вот к чему клоню: еще в конце 90-х ваша покорная слуга сотоварищи вовсю увлекалась обсуждением вещей, которые сейчас получили научное название «скрытые каналы передачи информации». Мы, тогда еще совсем юные сетевики, фантазировали, как можно использовать служебную информацию, содержащуюся в пакетах данных, для передачи некой высокоуровневой информации. И первое, что приходило в этой связи в голову – использовать последовательности пакетов с определенными характеристиками (в самом простом варианте это номер протокола, порт, установленные флаги) как своеобразные пароли или команды, с помощью которых можно общаться с удаленным хостом без установления соединений как в прямом (TCP), так и в переносном смысле слова (UDP хоть и является протоколом, не ориентированным на соединение, но все же требует от серверной стороны открытия UDP-порта). Однако никто из нас не отринул лень, дабы сесть написать пару сотен строк кода, реализующего эту не бог весть какую сложную идею. А вот Judd Vinet – известный разработчик свободного ПО из Британской Колумбии, автор дистрибутива Arch Linux – взял и написал свой knock, набор из сервера и клиента, реализующий вышеописанную идею. Полторы тысячи строк серверного кода плюс 167 строк клиентского приложения, которое, кстати, вообще опционально. Но не будем забегать вперед...
матчасть
Для начала расскажу, как это все хозяйство работает и для чего его можно использовать. Итак, серверная часть – knockd - сидит в системе и слушает проходящий по интерфейсам трафик, совсем как банальный сниффер. Инструментарий для захвата пакетов используется вполне стандартный – библиотека libpcap. Ее используют большинство юниксовых снифферов, она отлично написана, портабельна (работает на всех POSIX-совместимых ОС, под Windows тоже есть версия под названием WinPcap).
Заметив в потоке трафика определенную последовательность пакетов (описания таких последовательностей задает администратор системы в простеньком конфигурационном файле), knockd выполняет указанную в том же конфиге команду. Командой, как вы понимаете, может быть в данном контексте и одиночное действие, и здоровенный shell-script.
В качестве примера практического использования обычно приводят «случай с файрволлом и ssh». Вот, скажем, хотите вы максимально ограничить удаленный доступ к вашему серверу из внешних сетей. Полностью отказаться от того же ssh – идея на грани безумия/фантастики, мало ли что может случиться с удаленным хостом в наши времена... Можно с помощью файрволла разрешить доступ к ssh только с определенного адреса. Но опять же – если вы в командировке или на отдыхе за границей, сможете ли вы уверенно назвать IP-адреса того интернет-кафе, из которого вам придется работать? Вы возразите, что можно попросить кого-то прописать новый адрес на файрволле. Но если рядом с сервером кто-то есть, то почему бы ему не провести работы по его налаживанию самостоятельно, а? ;) Значит, имеем в виду, что рядом никого толкового может и не быть.
И вот тут knockd реально может помочь. Вы посылаете некую последовательность пакетов, и knockd командует файрволлу открыть для вашего текущего адреса доступ к порту ssh.
конкретика
Разберем ситуацию на примере. Допустим, есть следующие правила файрволла (в нашем примере это будет линуксовый netfilter/iptables):
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT tcp -- 192.168.0.100 0.0.0.0/0 tcp dpt:22
DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
То есть никому, кроме 192.168.0.100, на наш сервер на 22 порт TCP соваться нельзя.
Перед тем, как запустить knockd, пропишем ему в конфиг следующее:
[openSSH]
sequence = 7000,8000,9000
seq_timeout = 5
command = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn
[closeSSH]
sequence = 9000,8000,7000
seq_timeout = 5
command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn
Я думаю вам и без моих объяснений уже все понятно :) Но на всякий случай поясняю. Если knockd заметит последовательность из трех TCP-пакетов с выставленным флагом SYN (начало установления соединения) на порты 7000, 8000 и 9000 – добавит в начало списка правил файрволла строку, разрешающую адресу отправителя (то есть вашему текущему IP-адресу) соединяться с ssh. По завершении удаленной работы вы можете вернуть все, так сказать, на родину – последовательность аналогичных пакетов на порты 9000, 8000 и 7000 даст команду на удаление добавленного ранее правила. Доступ закрыт.
Еще раз хочу обратить ваше внимание на то, что руление вашим драгоценным файрволлом – не единственное возможное применение knockd. Мне показалось несколько курьезным, что в системе управления пакетами Gentoo Linux в списке зависимостей обнаружился iptables. Ну хорошо хоть, что эта зависимость числится там «желательной», а не обязательной. Но все равно народ смущает. Поэтому приведу свой собственный тестовый конфиг.
[hello world]
sequence = 60000,4000
seq_timeout = 30
command = echo “hello, world!” > /root/helloworld
tcpflags = syn
Как видите, последовательность можно взять произвольной длины, таймаут можно увеличить (потом станет понятно, зачем), а команда может делать что- то вовсе не связанное с файрволлом :)
Конечно же, это не все опции конфига. Во-первых, само собой разумеется, что можно сочетать в кодовой последовательности TCP- и UDP-пакеты. Можно указывать две команды – одна выполняется после получения кодовой последовательности, а другая по истечении некоторого таймаута... Подробнее все это описано в документации.
чем стучать*?
Чтобы послать нужную последовательность пакетов, мы можем воспользоваться самыми разнообразными инструментами. В стандартную поставку наряду с серверной частью входит и клиент под названием knock. Он умеет стучать по TCP и UDP, причем как всей пачкой (только TCP или только UDP), так и вразнобой. Плюсы использования этой утилиты очевидны: минимальные задержки между пакетами, интерфейс заточен именно под конкретную задачу. Есть и порт под Windows (Cygwin). Но есть минус: не везде вы сможете этой утилитой воспользоваться. Хорошо, если у вас ноутбук со всем необходимым софтом, а если придется работать из интернет-кафе? Или с чужой машины, где установка нового софта, пусть даже и такого мелкого, как knock, не приветствуется? Генераторы пакетов, утилиты типа hping, netcat, sendip в вашем распоряжении. Более того, если ваши кодовые последовательности не длинные, таймауты выставлены большие и используется только TCP, вы можете стучать всем, что попадется под руку – хоть telnet-ом, хоть браузером.
о безопасности
У скептиков, я думаю, уже накопилось много вопросов насчет безопасности такого решения. И первый вопрос, волнующий народ, я думаю, звучит так: «А что если последовательность будет подобрана или перехвачена?»
Насчет подбора – ну это философский вопрос :) Последовательность из произвольного (ну, скажем, так достаточно большого) количества пакетов, направленных на номера портов от 1 до 65535, выгодно отличается от пароля, в котором используется меньше вариантов составляющих (сложите буквы, цифры и символы, которые вы можете набрать с клавиатуры – сколько получается? ;)) Грамотный админ всегда отследит подбор пароля к сервисам, так почему подбор последовательности пакетов станет для него неожиданностью? ;)
С перехватом дела несколько хуже – действительно теоретически перехватить кодовую последовательность можно. Я говорю «теоретически», потому что хотелось бы мне взглянуть на психопата, просеивающего трафик в поисках неизвестно чего, разве что вы использовали стандартные последовательности из конфигов или слишком уж примечательные порты (ну вы же не будете так делать, правда? ;)
Но все же, поскольку теоретическую возможность перехвата мы признаем, взглянем на так сказать смягчающие обстоятельства.
Во-первых, вряд-ли вы будете использовать в качестве команды, запускаемой knockd, что-то вроде rm –rf / Маловероятно и то, что шпионы или террористы будут обсуждать с помощью такого скрытого канала свои страшные тайны. В общем, тут вопрос исключительно управления рисками – если риск небольшой, а удобство очевидно – пользуйтесь, да это касается не только knockd, но всех без исключения технических средств и технологий передачи данных, что я вам тут рассказываю...
Скорее всего большинство ограничатся описанной выше файрвольно-ssh-шной комбинацией. А у ssh есть свои вполне надежные методы авторизации и шифрования, файрволл просто добавляет второй рубеж защиты для особо параноидальных админов. Вот и будем это решение с такой точки зрения и рассматривать – дополнительный рубеж защиты, или достаточно наивное стеганографическое средство для не особо «тяжелых» случаев.
Во-вторых, для усиления защиты в knockd есть и штатное решение. Речь идет о так называемых одноразовых последовательностях. Эта штука напоминает кодовые карты, используемые для интернет-банкинга или для систем доступа в организациях с повышенными требованиями к безопасности. Идея проста – после каждого использования кодовая последовательность «сгорает», следующий раз она уже не сработает, нужно брать следующую по списку. Списки последовательностей для knockd представляют собой простые текстовые файлы, в каждой строке которого содержится одна последовательность в формате, аналогичном тому, что используется в директиве sequence конфигурационного файла. Подключение фичи одноразовых последовательностей происходит следующим образом:
one_time_sequences = /etc/knockd/smtp_sequences
где то, что после знака «=» - имя файла, содержащего список одноразовых последовательностей.
Стоит заметить, что клиентской программой эта фича как бы не поддерживается, то есть интерфейса для «скармливания» фалов кодовых
последовательностей у knock нет. Если этоих последовательностей немного и они не очень длинные, можно набивать их каждый раз вручную с некой электронной или бумажной шпаргалки на манер тех самых банковских кодовых карт. В противном случае вам придется написать некий «костыль» самостоятельно – unix way вам в помощь, господа.
послесловие
Я сознательно не стала описывать процедуру установки этого нехитрого софта, поскольку а) у каждого свои излюбленные методы добычи и установки пакетов (еще holy wars нам тут не хватало :) и б) эти бесконечные ./configure, make, make install ИМХО всех уже порядком достали. Да и, на мой взгляд, это разжевывание в некотором роде унижает продвинутых админов, коих, я полагаю, большинство среди читателей СР. Хотя две вещи все же скажу:
1. Сайт проекта доступен по адресу http://www.zeroflux.org/cgi-bin/cvstrac.cgi/knock/wiki.
2. Не забудьте удостовериться в наличии libpcap в вашей системе. При наличии отсутствия ;) – установите, Google вам в помощь.
За сим позвольте откланяться. И... Good knocking!
сноска
* knock по-английски, если кто не в курсе, означает «стук».
Alice D. Saemon
Сетевые решения. Статья была опубликована в номере 07 за 2006 год в рубрике sysadmin