Почему мой tar через ssh (команда через author_keys) портит архив?
С бэкапа я хочу вытащить дампы tgz рабочего сервера. Обе машины работают под управлением Ubuntu 16.04.
Поэтому резервный сервер подключается через ssh и определенный ssh к производственному серверу.
~/.ssh/authorized_keys
Файл соответствующего пользователя на производственном сервере должен просто разрешать одну команду и накладывать как можно больше ограничений (надеюсь?):
command="tar -cz --file - --ignore-command-error --ignore-failed-read /dir/ 2>/dev/null | cat",no-agent-forwarding,no-port-forwarding,no-user-rc,no-X11-forwarding ssh-rsa AABLASHKEY comment
где /dir/
каталог для резервного копирования, AABLASSHKEY
а также comment
"реальные" значения, конечно.
| cat
в этом случае требуется, потому что иначе tar в этой версии ubuntu ("tar (GNU tar) 1.28") не будет говорить с stdout, заданным ssh (PTY). Стдерр должен уйти в пустоту (2> /dev/null
).Изменить: точка зрения о PTY является заблуждение, см. Ответ @grawity.
На принимающей стороне (backup
сервер) Я поднимаю это так:
ssh -i /path/to/key the-user@production-server > dir.tgz
Однако полученный файл отличается по размеру от архива, если я создаю его на сервере, и он не является допустимым архивом (например, gzip: stdin: invalid compressed data--crc error ... gzip: stdin: invalid compressed data--length error
). Разница в размере составляет 22 байта.
Если я разрешу резервному серверу любую команду на производительном сервере, сняв ограничения в authorized_keys
это работает отлично. В какой момент я скучаю?
Ограничения
- Я очень хочу использовать
tar
(не Rsync, Rrsync или что-то в этом роде). - Соединение должно быть инициировано резервным сервером
- Рабочий сервер не должен создавать никаких временных файлов
Решение
Как указал @Grawity в своем ответе (прочитайте его, чтобы очистить некоторые заблуждения), следующую строку в ~.ssh/authorized_keys
решает проблему (и работает на Ubuntu 16.04 с данной версией OpenSSH):
command="tar -cz --file - --ignore-command-error --ignore-failed-read /dir/ 2>/dev/null",restrict ssh-rsa ....
Чтобы команда back-up-server не выдавала предупреждений, подключитесь к:
ssh -o RequestTTY=no -i /path/to/key the-user@production-server > dir.tgz
1 ответ
| cat
в этом случае требуется, потому что иначе tar […] не будет говорить с stdout, заданным ssh (PTY).
Нет. Наличие PTY - это точно одна из ваших проблем. Слой tty существует для обработки управляющих символов терминала и совершенно не нужен для других типов данных.
Обычно работает SSH в пакетном режиме (т.е. ssh <host> <cmd>
) не будет выделять серверную часть PTY; это обеспечит 8-битный чистый канал. Но когда вы не предоставляете команду на клиенте, вам нужно явно добавить -T
или же RequestTTY
опция клиента для отключения запроса TTY,
ssh -T theuser @ prod> dir.tgz ssh -o RequestTTY = no theuser @ prod> dir.tgz
или предоставьте фиктивную команду,
ssh theuser @ prod foo > dir.tgz
или запретить такие запросы с no-pty
опция author_keys:
command = "tar -czf - / dir / 2> / dev / null", no-pty, ограничить ssh-rsa ABCDEF
( restrict
это недавно добавленный псевдоним, который отключает все переадресации сразу, включая те, которые могут быть добавлены в будущем. Доступно с OpenSSH 7.2. На самом деле, это даже включает в себя no-pty
, хотя я перечислил это отдельно для этого ответа.)