четверг, 1 декабря 2016 г.

GRAYLOG, настройка.

Источник, спасибо автору

Вместо введения: Graylog это open source программное обеспечение, предназначенное для сбора логов в гигантских сетях их огромного количества источников различными способами. В нем можно удобно организовать сбор событий, фильтрацию, поиск, автоматизацию (всякие алерты) и т.д. Аналогичных средств множество, но Graylog предлагает нереальную производительность с использованием современных компонентов, удобную аналитику и красивый интерфейс.
Для работы ему нужна Java, конфигурацию он будет хранить в MongoDB, для поиска и хранения логов — использовать ElasticSearch. Про сбор информации из WIndows будет ниже, но спойлер — агенту больше не нужна Java.
 
Вторая часть: настройка приема логов в Graylog из Linux. (видеоинструкция)

В консоль сервера приема логов нам больше попадать не нужно. Идем в веб-морду и создаем Input для логов. Расписывать навигацию по веб-интерфейсу дело гиблое, потому есть видео. Если кратко:
  • в меню «Система» создается UDP Input;
  • указывается syslog udp;
  • указывается порт (по умолчанию 512, но чтобы graylog мог использовать порты ниже 1024 нужно много возьни), поэтому, например 1234;
  • указывается адрес для прослушивания входящих сообщений, у меня 10.0.1.10;
  • нажимаем Launch.

Для проверки работы Input можно в консоли того же сервера graylog выполнить
echo "Hello Graylog" | nc -w 1 -u 10.0.1.10 1234
и посмотреть в веб-интерфейсе сообщения, полученные на Input.

Конфигурация машин Linux на отправку логов, в принципе проста. Почти везде релизы syslogd ведут себя одинаково. Кто ничего не помнит о демонах журналирования — освежите память у меня на канале. Итак debian и redhat.
Создается файл задания rsyslog:
 sudo vi /etc/rsyslog.d/90-graylog2.conf

c текстом (адрес и порт взят из настроенного Input):
$template GRAYLOGRFC5424,"<%PRI%>%PROTOCOL-VERSION% %TIMESTAMP:::date-rfc3339% %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg%\n"
*.* @10.0.1.10:1234;GRAYLOGRFC5424


Демон журналов перезапукается командой
sudo service rsyslog restart
(ну или как там в вашей ОС).
И можно смотреть в веб-интерфейсе Graylog полученные сообщения.

Третья часть: настройка приема логов в Graylog из Windows. (видеоинструкция)

В версиях Graylog младше второй использовался graylog collector на java. Во второй (актуальной) он просто игнорируется и дает ошибки (полдня пытался починить, пока не понял это). Вместо него используется graylog sidecar, который получает конфиг с сервера Graylog (что очень удобно, так как нет необходимости лазить по виндовым серверам для редактирования настроек) и передает его в nxlog (или что вам больше нравится), который события собирает и отправляет.
image

Для приема сообщений из Windows надо создать отдельный Input через веб-интерфейс:
  • выбираем GELF UDP;
  • указываем узел, айпишник сервера graylog;
  • запоминаем или редактируем порт приема сообщений (по умолчанию 12201).


Для создания конфигурации отправки логов для nxlog на винде, нужно создать коллектор через веб-интерфейс в graylog:
  • выбираем Collectors;
  • выбираем Manage Configuration;
  • создаем конфигурацию;
  • указываем метку (именно по метке sidecar на windows поймет какую конфигурацию для nxlog ему скачивать к себе на машину);
  • создаем Output для nxlog (в котором просто указываем настройки Input из предыдущего шага: GELF UDP Output, ip, порт);
  • создаем Input для nxlog (указываем простейший вариант: Windows Event Log).


Отправляемся в Windows, Скачиваем и устанавливаем nxlog и graylog-sidecar.
Убираем как службу nxlog, и ставим как службу sidecar:
'C:\Program Files (x86)\nxlog\nxlog.exe' -u
'C:\Program Files (x86)\graylog\collector-sidecar\graylog-collector-sidecar.exe' -service install


Редактируем файл конфигурации Sidecar (C:\Program Files (x86)\graylog\collector-sidecar\collector_sidecar.yml), а именно указываем порт прослушки глобальный (12900), ip сервера, и самое главное: метку, по которой будет принят конфиг. У меня это выглядит так:
server_url: http://10.0.1.10:12900
node_id: graylog-collector-sidecar
collector_id: file:C:\Program Files (x86)\graylog\collector-sidecar\collector-id
tags: windows
log_path: C:\Program Files (x86)\graylog\collector-sidecar
update_interval: 10
backends:
- name: nxlog
enabled: true
binary_path: C:\Program Files (x86)\nxlog\nxlog.exe
configuration_path: C:\Program Files (x86)\graylog\collector-sidecar\generated\nxlog.conf


Запускаем sidecar 'C:\Program Files (x86)\graylog\collector-sidecar\graylog-collector-sidecar.exe' -service start

Создаем событие eventcreate /l Application /t INFORMATION /id 1 /d “Suck it”

Смотрим логи в его директории (C:\Program Files (x86)\graylog\collector-sidecar\), и если все ок — отправляемся в веб-морду смотреть логи винды на инпуте.

Нюансы:
  1. бывает что файл конфига нужно создать вручную пустой C:\Program Files (x86)\graylog\collector-sidecar\generated\nxlog.conf;
  2. бывает что нужно перезапустить винду, чтобы все сервисы все схватили;
  3. у меня был косяк с опечаткой в названии метки, убил час, разбираясь;
  4. сама метка должна отметиться в веб-интерфейсе в рамочку, иначе это не метка.


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

среда, 12 октября 2016 г.

Docker, передача параметров демону в ubuntu / debian

Источник

After a look around at the configuration files in /lib/systemd/system/, it seems that the Docker configuration file (/lib/systemd/system/docker.service) is not using /etc/default/docker at all.

  The problem is solved by adding an EnvironmentFile directive and modifying the command line to include the options from the file, e.g.
 
[Unit]
Description=Docker Application Container Engine
Documentation=http://docs.docker.com
After=network.target docker.socket
Requires=docker.socket

[Service]
EnvironmentFile=-/etc/default/docker
ExecStart=/usr/bin/docker -d $DOCKER_OPTS -H fd://
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity

[Install]
WantedBy=multi-user.target 
 
You have to edit /lib/systemd/system/docker.service to look like the above, 
run systemctl daemon-reload, and then restart the Docker service. 

четверг, 29 сентября 2016 г.

postfix-policyd-spf-python

Источник, спасибо автору.

  • Устанавливаем необходимые пакеты:
    # aptitude install postfix-policyd-spf-python
  • Добавляем в /etc/postfix/main.cf
    policy-spf_time_limit = 3600s
    Далее ищем объявление smtpd_recipient_restrictions и добавляем в него (после reject_unauth_destination) строку check_policy_service unix:private/policy-spf.
    ...
     reject_unauth_destination
     check_recipient_access hash:/etc/postfix/roleaccount_exceptions
     reject_non_fqdn_hostname
     check_helo_access pcre:/etc/postfix/pcre_helo_checks.cf
     check_sender_mx_access cidr:/etc/postfix/cidr_mx_access
     check_policy_service unix:private/policy-spf
     permit
  • Переходим к файлу /etc/postfix/master.cf: в него добавляем следующую строку:
    policy-spf  unix  -       n       n       -       0       spawn
      user=nobody argv=/usr/bin/policyd-spf /etc/postfix-policyd-spf-python/policyd-spf.conf
  • Дополнительные настройки в файле /etc/postfix-policyd-spf-python/policyd-spf.conf и описания настроек в файле policyd-spf.conf.commented.
    policyd-spf.conf
    #  For a fully commented sample config file see policyd-spf.conf.commented
     
    debugLevel = 1
    # Этот параметр определяет, отбрасывать ли действительно письма,
    # если они нарушают SPF, или просто писать об этом в логи и пропускать
    defaultSeedOnly = 1
     
    HELO_reject = SPF_Not_Pass
    # SPF_Not_Pass =
    # Отбрасываем все сообщения, кроме:
    # 1. которые прошли SPF-валидацию
    # 2. В домене нет SPF записи
    # 3. Произошла временная ошибка (DNS упал?)
    Mail_From_reject = Fail
     
    PermError_reject = False
    # При наличии ошибок при проверке пропускаем почту
    TempError_Defer = False
     
    # перечисляйте IPs без пробелов
    skip_addresses = 127.0.0.0/8,::ffff:127.0.0.0/104,::1,10.26.95.0/24
     
    #  Domain_Whitelist: List of domains whose sending IPs (defined by passing
    #  their SPF check should be whitelisted from SPF.
    #  Example (default is no domain whitelist):
    Domain_Whitelist = example1.com,example2.com
    Для дополнительно информации читаем справку
    man policyd-spf.conf
Для применения изменений в файле policyd-spf.conf обязательно перегрузите postfix
# service postfix restart

четверг, 22 сентября 2016 г.

Openfire. Howto get message history from database

1) PostgreSQL
 SELECT
'1970-01-01 00:00:00 GMT'::timestamp with time zone + ((ofmessagearchive.sentdate/1000)::text)::interval AS time,
ofmessagearchive.fromjid AS from,
ofmessagearchive.tojid AS to,
ofmessagearchive.body AS message
FROM
public.ofmessagearchive
WHERE
( ofmessagearchive.fromjid = '<JID of user>'
OR
ofmessagearchive.tojid = '<JID of user>' )
AND
ofmessagearchive.sentdate > EXTRACT(EPOCH FROM timestamp with time zone 'start time in format <YYYY-MM-DD HH-MM-SS>') * 1000
AND
ofmessagearchive.sentdate < EXTRACT(EPOCH FROM timestamp with time zone 'end time in format <YYYY-MM-DD HH-MM-SS>') * 1000
ORDER BY 1;

четверг, 25 августа 2016 г.

How to Recover from a Lost SA Password in SQL Server 2012

Source.

Working at Microsoft provides many opportunities to receive pearls of wisdom from individuals at other parts of the organization.  Saleem Hakani sent along this little gem a few days ago and I wanted to share it with you.  It outlines how to recover an SA password if you forgot it – though you do need to shutdown your SQL Server instance and start it in maintenance mode to accomplish this. 
What I have done in the past as well is recommend  that customers write the SA password down, put it in an envelope and put that envelope in a safe that requires two people to get authorized access to.  This way no one person can get the SA password (two are required) and you don’t need to shut down the server to get it, if needed.
Enjoy!

Here’s the scenario:

You are a proud and a trusted DBA of your organization who is responsible for some important services running on SQL Servers in the production environment. To prevent any unauthorized access to your production environment, you have decided to perform the following steps that are kind of best practices to secure your company’s SQL Servers from any unauthorized access:

þ  You have removed any and all built-in administrators account from SQL Server logins.
þ  You have removed all users (except SA) that were part of SYSADMIN server role (Including any Windows Accounts and/or SQL Server logins)
þ  You have set the password of SA account to something extremely complex which would be hard for anyone to guess or remember.
þ  For day-to-day operations on SQL Server, you use your domain user account which has DBO permissions on user databases but doesn’t have SYSADMIN privileges on the system.
þ  You have not documented the SA password anywhere to prevent others from knowing the SA password. (Also, it’s not a good practice to document the password)

Since you have set the SA password to be complex and you have been using your domain account and not the SA account for all your daily database related activity on SQL Server, the unthinkable has happened “you forgot your SQL Server’s SA password”. You are the only person who knew the SA password in your team and now you don’t remember what it was and you need to make some server level configuration changes to your production SQL Server boxes.

What would you do now? Here are some of the options I think you may do:
1.       You will try logging in as SA with all possible passwords you have in your mind.
2.       You will look for the SA password on your computer hard-drive or in your emails (If you had stored it in some file which is a bad practice)
3.       Try to restore MASTER database from database backup. However, this will not help because you will run in to the same issue as you don’t remember the SA password.
4.       Rebuild Master database. This may not help as you will lose all system/server level configurations and settings including logins, permissions and any server level objects.
5.       Re-install SQL Server 2012 and attach all user databases. This may not work as you may experience same issues that you would experience with #4.

All your attempts to login in to the system using SA password have failed and now it is time for you to call up the world’s best product support services team “Microsoft PSS”

Here’s what you can do:
Many folks have asked me about this and today, I’d like to share with you a backdoor to SQL Server 2012 which would help you gain SYSADMIN access to your production SQL Servers. However, that would mean your Windows account will need to be a member of the local administrators group on Windows Servers where SQL Server 2012 Services are running.

SQL Server allows any member of Local Administrators group to connect to SQL Server with SYSADMIN privileges.

Steps to take control of your SQL Server 2012 as an SA:

1.       Start the SQL Server 2012 instance using single user mode from command prompt by launching  the command prompt as an administrator. (Note: You can also start SQL Server 2012 using minimal configuration which will also put SQL Server in single user mode)

2.       From the command prompt (Run as Administrator) type: SQLServr.Exe –m (or SQLServr.exe –f) and let the SQL Server 2012 database engine start. Make sure you do not close this command prompt window.

You can locate SQLServr.exe in the Binn folder of your environmental path. If you don’t have SQL Server 2012 Binn folder in your environmental path, you can always navigate to the Binn folder of your SQL Server 2012 machine. Usually the Binn folder is located @ C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Binn>

3.       Once SQL Server 2012 service has been started in single user mode or with minimal configuration, you can now open up another command line window as an administrator and use SQLCMD command from command prompt to connect to SQL Server 2012 instance:

SQLCMD –S <Server_Name\Instance_Name>

Example:
SQLCMD –S “SALEEMHAKANI”


You will now be logged in to SQL Server. Keep in mind that you are now logged in as an Admin on SALEEMHAKANI SQL Server 2012 instance.

4.       Once you are logged into the SQL Server 2012 using SQLCMD from the command prompt, you have the option of creating a new account and granting it any server level permission.

Let’s create a new login in SQL Server 2012 called “Saleem_SQL” and then add this account to SysAdmin server role.

To create a new login from the command prompt after performing Step 3:
1> CREATE LOGIN ‘<Login_Name>’ with PASSWORD=’<Password>’
2> GO

Example:
1>     CREATE LOGIN SQL_SALEEM WITH PASSWORD=’$@L649$@m’
2>     GO

To Once the new login “SQL_SALEEM” has been created, now let’s add this login to System Admin server role on SQL Server 2012 instance.

From the same command prompt window, execute the following statement:

1> SP_ADDSRVROLEMEMBER ‘<Login_Name>’,’SYSADMIN’
2>go
Example:
1>     SP_ADDSRVROLEMEMBER SQL_SALEEM,’SYSADMIN’
2>     GO

The above operation will take care of granting SYSADMIN privileges to “SQL_SALEEM” login.

5.       Once the above steps are successfully performed, the next step is to stop and start SQL Server services using regular startup options. (This time you will not need –f or –m)

6.       Log in to the SQL Server 2012 management studio or from the command prompt using “SQL_SALEEM” account and it’s respective password, you now have system admin access to your SQL Server 2012 instance. You may now reset the SA password and take control of your production SQL Server boxes.

How To Free Reserved Space On EXT4 Partitions

Source.

This one came in handy when I bought a 1TB hard drive last week. Most linux distributions reserve 5% of new partitions for the root user and system services. The idea here is even when you run out of disk space, the root user should still be able to log in and system services should still run… this won’t happen if there is no space on the root partition. This policy may have been appropriate in the 90s when hard disk capacities were relatively low but this is 2010 and one can get a 1TB hard drive for a couple of hundred Ghana Cedis. 5% of that is about 51GB and those system services need only a couple of hundred megabytes.
So I decided to reclaim all that disk real estate with this command:

sudo tune2fs -m 0 /dev/sdb1

This sets the reserved blocks to 0%. This is an additional storage drive, I have no need to reserve disk space for system services. You can verify that this actually worked with:

sudo tune2fs -l /dev/sdb1 | grep ‘Reserved block count’
As usual, modify /dev/sdb1 to suit your partition setup. Have fun.

четверг, 2 июня 2016 г.

Howto permanently set ulimit -n 8192 in Centos 7

Source

I would like to permanently set the open file limit for all users in Centos 7, but there seems to be a lot of conflicting information out there on the googles.

Examples:

1) If you want to increase file limit for system service you'll have to edit /usr/lib/systemd/system/SOME_SERVICE.service
add LimitNOFILE,
[Service]
...
LimitNOFILE=8192
and run systemctl daemon-reload to activate changes.

2) It could be done by creating new config file in: /etc/security/limits.d/ (to be on safe side when upgrading etc). For example:
/etc/security/limits.d/nofile.conf
with content as written before by sysadmin1138:
*    soft    nofile 8192
*    hard    nofile 8192

Синхронизация локальных и удалённых каталогов при помощи lsyncd

Источник

Что такое lsyncd?

При управлении веб-сервером или приложением часто возникает необходимость синхронизировать каталоги. Одним из надёжных решений для выполнения этой задачи является демон lsyncd.
В данном руководстве показано, как настроить lsyncd для синхронизации изменений в каталогах на одной машине и между удалёнными хостами.
Примечание: Данное руководство выполнено на виртуальном выделенном сервере Ubuntu 12.04, но любой современный дистрибутив будет работать таким же образом.

Установка lsyncd

Демон lsyncd можно скачать из официального репозитория Ubuntu.
Чтобы установить lsyncd, используйте команды:
sudo apt-get update
sudo apt-get install lsyncd

Эти команды установят lsyncd. Но демон поставляется без стандартных настроек, потому их необходимо установить самостоятельно.

Примеры конфигурации lsyncd

Демон lsyncd не имеет стандартного конфигурационного файла, но предоставляет несколько примеров конфигураций, которые можно найти в каталоге /usr/share/doc/lsyncd/examples:
cd /usr/share/doc/lsyncd/examples
ls
lbash.lua  lgforce.lua      lpostcmd.lua  lrsyncssh.lua
lecho.lua  limagemagic.lua  lrsync.lua

Ознакомьтесь с этими текстовыми файлами, чтобы понять, как устроены конфигурации lsyncd.
Более подробные настройки можно найти в файле lrsync.lua:
sudo nano
----
-- User configuration file for lsyncd.
--
-- Simple example for default rsync.
--
settings = {
statusFile = "/tmp/lsyncd.stat",
statusIntervall = 1,
}
sync{
default.rsync,
source="src",
target="trg",
}

Строки, которые начинаются с двух тире (—), закомментированы, lsyncd не интерпретирует их.
Конфигурационный файл lsync написан ан языке программирования Lua; узнать больше о Lua можно здесь.

Настройка окружения

Для примера попробуйте синхронизировать два локальных каталога. Создайте их при помощи следующей команды:
sudo mkdir -p /source/to/copy
sudo mkdir /dest

Затем нужно добавить несколько файлов в первый каталог:
cd /source/to/copy
sudo touch file{1..100}

Эти команды создают 100 файлов в каталоге /source/to/copy.
Кроме того, нужно создать лог для lsyncd и несколько файлов в нём:
sudo mkdir /var/log/lsyncd
touch /var/log/lsyncd/lsyncd.{log,status}

Затем нужно создать конфигурационный каталог lsyncd:
sudo mkdir /etc/lsyncd
В этом каталоге создайте конфигурационный файл lsyncd.conf.lua:
sudo nano /etc/lsyncd/lsyncd.conf.lua

Синхронизация локальных каталогов при помощи lsyncd

При помощи только что созданного конфигурационного файла можно синхронизировать каталоги /source/to/copy directory to the /dest.

Основные настройки

Основные настройки находятся в разделе settings; поместите в файл:
settings = {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status"
}

Благодаря этим опциям lsyncd будет использовать созданные ранее файлы.

Настройки синхронизации

Следующий раздел содержит настройки синхронизации. Поскольку в данном случае синхронизация будет выполняться локально, можно использовать команду rsync.
Эти конфигурации определяются при помощи опции default.rsync, которая значит, что демон lsyncd будет ждать 20 секунд или собирать 1000 отдельных событий синхронизации, а затем вызовет rsync для синхронизации изменений.
Согласно мануалу lsyncd вызываемая команда rsync эквивалентна команде:
rsync -ltsd --delete --include-from=- --exclude=* SOURCE TARGET
Это значит, что rsync работает следующим образом:
  • -l: копирует символическую ссылку
  • -t: копирует время изменения
  • -s: только подстановочные знаки
  • -d: перемещение каталогов без рекурсии
Всё, что нужно сделать, чтобы изменения вступили в силу — указать тип синхронизации, исходный и целевой каталог. Раздел sync должен выглядеть так:
sync {
default.rsync,
source = "/source/to/copy",
target = "/dest"
}

Чтобы изменить поведение rsync при помощи опций, задайте переменной rsyncOpts список этих опций, разделив их запятыми:
sync {
default.rsync,
source = "/source/to/copy",
target = "/dest",
rsyncOpts = {"rsync option1", "rsync option2", "rsync option3"}
}

Теперь файл готов к тестовой синхронизации; сохраните и закройте файл.

Тестовая локальная синхронизация

Откройте целевой каталог и убедитесь, что он пуст (в данном случае это /dest):
cd /dest
ls

Последняя команда не должна вернуть никакого вывода, поскольку каталог пуст.
Перезапустите сервис  lsyncd, выполнив команду:
sudo service lsyncd start
Снова выполните команду ls:
ls
file1    file18  file27  file36  file45  file54  file63  file72  file81  file90
file10   file19  file28  file37  file46  file55  file64  file73  file82  file91
file100  file2   file29  file38  file47  file56  file65  file74  file83  file92
file11   file20  file3   file39  file48  file57  file66  file75  file84  file93
file12   file21  file30  file4   file49  file58  file67  file76  file85  file94
file13   file22  file31  file40  file5   file59  file68  file77  file86  file95
file14   file23  file32  file41  file50  file6   file69  file78  file87  file96
file15   file24  file33  file42  file51  file60  file7   file79  file88  file97
file16   file25  file34  file43  file52  file61  file70  file8   file89  file98
file17   file26  file35  file44  file53  file62  file71  file80  file9   file99

Как видите, демон lsyncd успешно синхронизировал локальные каталоги.
Если в исходный каталог добавить несколько файлов, то с задержкой в 20 секунд они появятся в целевом каталоге.
sudo mkdir /source/to/copy/hello{1..100}
ls

Затем проверьте целевой каталог при помощи команды ls.

Удалённая синхронизация при помощи lsyncd

Чтобы настроить удалённую синхронизацию, нужно внести несколько изменений в конфигурационный файл.
Для начала нужно иметь возможность подключиться к машине по ssh.

Подключение к удалённой машине с помощью SSH-ключей

Чтобы получить инструкции по созданию SSH-ключей, читайте данное руководство.
Создайте пару ключей для root-пользователя, поскольку lsyncd будет работать как root. Затем скопируйте файл ключа на удалённую машину при помощи команды:
sudo su
ssh-copy-id remote_mirror_ip_address

Теперь файл ключа позволит входить на удалённый сервер как пользователю root.
Убедитесь, что это работает, и создайте на удалённой машине целевой каталог:
ssh remote_mirror_ip_address
Для примера создайте целевой каталог /remotesync:
mkdir /remotesync
Закройте удалённую сессию и локальную root-сессию, дважды введя exit:
exit
exit

Настройка удалённой синхронизации lsyncd

Откройте конфигурационный файл lsyncd:
sudo nano /etc/lsyncd/lsyncd.conf.lua
settings = {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status"
}
sync {
default.rsync,
source = "/source/to/copy",
target = "/dest"
}

Нужно внести некоторые изменения в раздел sync:
Замените default.rsync на default.rsyncssh, чтобы включить поддержку rsync по ssh; также замените переменную target переменными host и targetdir:
settings = {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status"
}
sync {
default.rsyncssh,
source = "/source/to/copy",
host = "remote_mirror_ip_address",
targetdir = "/remotesync"
}

Сохраните и закройте файл.

Тестирование удалённой синхронизации

Перезапустите сервис lsyncd:
sudo service lsyncd restart
Подключившись к удалённой машине по ssh, можно увидеть изменения в каталоге /remotesync:
sudo su
ssh remote_mirror_ip_address
ls /remotesync

Теперь этот каталог содержит файлы, добавленные в каталог /source/to/copy.

Заключение

Сервис lsyncd — отличный способ синхронизировать файлы между системами и каталогами. Написанный на Lua конфигурационный файл делает этот инструмент ещё более гибким и производительным. Документация Lua и lsyncd содержат инструкции для настройки более сложной синхронизации.
Кроме того, помните, что каталог /usr/share/doc/lsyncd/examples содержит и другие примеры конфигурационных файлов.

понедельник, 30 мая 2016 г.

How to Back Up and Restore a MySQL Database

Source

If you're storing anything in MySQL databases that you do not want to lose, it is very important to make regular backups of your data to protect it from loss. This tutorial will show you two easy ways to backup and restore the data in your MySQL database. You can also use this process to move your data to a new web server.
Back up From the Command Line (using mysqldump)
If you have shell or telnet access to your web server, you can backup your MySQL data by using the mysqldump command. This command connects to the MySQL server and creates an SQL dump file. The dump file contains the SQL statements necessary to re-create the database. Here is the proper syntax:
$ mysqldump --opt -u [uname] -p[pass] [dbname] > [backupfile.sql]
  • [uname] Your database username
  • [pass] The password for your database (note there is no space between -p and the password)
  • [dbname] The name of your database
  • [backupfile.sql] The filename for your database backup
  • [--opt] The mysqldump option
For example, to backup a database named 'Tutorials' with the username 'root' and with no password to a file tut_backup.sql, you should accomplish this command:
$ mysqldump -u root -p Tutorials > tut_backup.sql
This command will backup the 'Tutorials' database into a file called tut_backup.sql which will contain all the SQL statements needed to re-create the database.
With mysqldump command you can specify certain tables of your database you want to backup. For example, to back up only php_tutorials and asp_tutorials tables from the 'Tutorials' database accomplish the command below. Each table name has to be separated by space.
$ mysqldump -u root -p Tutorials php_tutorials asp_tutorials > tut_backup.sql
Sometimes it is necessary to back up more that one database at once. In this case you can use the --database option followed by the list of databases you would like to backup. Each database name has to be separated by space.
$ mysqldump -u root -p --databases Tutorials Articles Comments > content_backup.sql
If you want to back up all the databases in the server at one time you should use the --all-databases option. It tells MySQL to dump all the databases it has in storage.
$ mysqldump -u root -p --all-databases > alldb_backup.sql
The mysqldump command has also some other useful options:
--add-drop-table: Tells MySQL to add a DROP TABLE statement before each CREATE TABLE in the dump.
--no-data: Dumps only the database structure, not the contents.
--add-locks: Adds the LOCK TABLES and UNLOCK TABLES statements you can see in the dump file.
The mysqldump command has advantages and disadvantages. The advantages of using mysqldump are that it is simple to use and it takes care of table locking issues for you. The disadvantage is that the command locks tables. If the size of your tables is very big mysqldump can lock out users for a long period of time.
Back up your MySQL Database with Compress
If your mysql database is very big, you might want to compress the output of mysqldump. Just use the mysql backup command below and pipe the output to gzip, then you will get the output as gzip file.
$ mysqldump -u [uname] -p[pass] [dbname] | gzip -9 > [backupfile.sql.gz]
If you want to extract the .gz file, use the command below:
$ gunzip [backupfile.sql.gz]
Restoring your MySQL Database
Above we backup the Tutorials database into tut_backup.sql file. To re-create the Tutorials database you should follow two steps:
  • Create an appropriately named database on the target machine
  • Load the file using the mysql command:
$ mysql -u [uname] -p[pass] [db_to_restore] < [backupfile.sql]
Have a look how you can restore your tut_backup.sql file to the Tutorials database.
$ mysql -u root -p Tutorials < tut_backup.sql
To restore compressed backup files you can do the following:
gunzip < [backupfile.sql.gz] | mysql -u [uname] -p[pass] [dbname]
If you need to restore a database that already exists, you'll need to use mysqlimport command. The syntax for mysqlimport is as follows:
mysqlimport -u [uname] -p[pass] [dbname] [backupfile.sql]
Backing Up and Restoring using PHPMyAdmin
It is assumed that you have phpMyAdmin installed since a lot of web service providers use it. To backup your MySQL database using PHPMyAdmin just follow a couple of steps:
  • Open phpMyAdmin.
  • Select your database by clicking the database name in the list on the left of the screen.
  • Click the Export link. This should bring up a new screen that says View dump of database (or something similar).
  • In the Export area, click the Select All link to choose all of the tables in your database.
  • In the SQL options area, click the right options.
  • Click on the Save as file option and the corresponding compression option and then click the 'Go' button. A dialog box should appear prompting you to save the file locally.
Restoring your database is easy as well as backing it up. Make the following:
  • Open phpMyAdmin.
  • Create an appropriately named database and select it by clicking the database name in the list on the left of the screen. If you would like to rewrite the backup over an existing database then click on the database name, select all the check boxes next to the table names and select Drop to delete all existing tables in the database.
  • Click the SQL link. This should bring up a new screen where you can either type in SQL commands, or upload your SQL file.
  • Use the browse button to find the database file.
  • Click Go button. This will upload the backup, execute the SQL commands and re-create your database.

Проброс и перенаправление портов средствами iptables

Источник, благодарю автора.

Допустим, мы находимся в локальной сети и от внешнего мира отделены шлюзом под управлением Linux.
В этой же локальной сети находятся сервера, которые должны предоставлять услуги внешнему миру. Например, web-сервер, ftp, почтовый сервер или все вместе одновременно.
Понятно, что доступ извне должен осуществляться через внешний адрес шлюза. И в зависимости от типа входящего соединения (которое определяется портом, например 80 - веб сервер, 21 - FTP), шлюз должен перенаправлять его на соответствующий сервер локальной сети.
Это и есть проброс портов.
Рассмотрим, как реализовать его средствами iptables.
Вначале договоримся о сокращениях и умолчаниях:
$EXT_IP - внешний, реальный IP-адрес шлюза
$INT_IP - внутренний IP-адрес шлюза, в локальной сети
$LAN_IP - внутренний IP-адрес сервера, предоставляющего службы внешнему миру
$SRV_PORT - порт службы. Для веб-сервера равен 80, для SMTP - 25 и т.д.
eth0 - внешний интерфейс шлюза. Именно ему присвоен сетевой адрес $EXT_IP
eth1 - внутренний интерфейс шлюза, с адресом $INT_IP
А для облегчения понимания, в таких блоках будем рассматривать конкретную ситуацию:
1.2.3.4 - внешний адрес шлюза
192.168.0.1 - внутренний адрес шлюза
В локальной сети работает веб-сервер (порт 80) для сайта webname.dom
192.168.0.22 - внутренний адрес веб-сервера

Проброс портов

Итак, пакет пришёл на шлюз. Мы должны перенаправить его на нужный сервер локальной сети перед принятием решения о маршрутизации, то есть - в цепочке PREROUTING таблицы nat.
iptables -t nat -A PREROUTING --dst $EXT_IP -p tcp --dport $SRV_PORT -j DNAT --to-destination $LAN_IP
iptables -t nat -A PREROUTING --dst 1.2.3.4 -p tcp --dport 80 -j DNAT --to-destination 192.168.0.22
Читай: если входящий пакет пришёл извне на шлюз (1.2.3.4), но предназначен веб-серверу (порт 80), то адрес назначения подменяется на локальный адрес 192.168.0.22. И впоследствии маршрутизатор передаст пакет в локальную сеть.
Дальше принимается решение о маршрутизации. В результате пакет пойдёт по цепочке FORWARD таблицы filter, поэтому в неё надо добавить разрешающее правило. Оно может выглядеть, например, так:
iptables -I FORWARD 1 -i eth0 -o eth1 -d $LAN_IP -p tcp -m tcp --dport $SRV_PORT -j ACCEPT
iptables -I FORWARD 1 -i eth0 -o eth1 -d 192.168.0.22 -p tcp -m tcp --dport 80 -j ACCEPT
Пропустить пакет, который пришёл на внешний интерфейс, уходит с внутреннего интерфейса и предназначен веб-серверу (192.168.0.22:80) локальной сети.
С одной стороны, этих двух правил уже достаточно для того, чтобы любые клиенты за пределами локальной сети успешно подключались к внутреннему серверу. С другой - а что будет, если попытается подключиться клиент из локальной сети? Подключение просто не состоится: стороны не поймут друг друга.
Допустим, 192.168.0.333 - ip-адрес клиента внутри локальной сети.
  1. сотрудник вводит в адресную строку браузера адрес webname.dom
  2. компьютер обращается к DNS и разрешает имя webname.dom в адрес 1.2.3.4
  3. маршрутизатор понимает, что это внешний адрес и отправляет пакет на шлюз
  4. шлюз, в соответствии с нашим правилом, подменяет в пакете адрес 1.2.3.4 на 192.168.0.22, после чего отправляет пакет серверу
  5. веб-сервер видит, что клиент находится в этой же локальной сети (обратный адрес пакета - 192.168.0.333) и пытается передать данные напрямую клиенту, в обход шлюза
  6. клиент игнорирует ответ, потому что он приходит не с 1.2.3.4, а с 192.168.0.22
  7. клиент и сервер ждут, ведут себя как «две целки на морозе», связи и обмена данными нет
Есть два способа избежать подобной ситуации.
Первый - чётко разграничивать обращения к серверу изнутри и извне.
Создать в локальном DNS-сервере A-запись для webname.dom, указывающую на 192.168.0.22.
Второй - с помощью того же iptables заменить обратный адрес пакета.
Правило должно быть добавлено после принятия решения о маршрутизации и перед непосредственной отсылкой пакета. То есть - в цепочке POSTROUTING таблицы nat.
iptables -t nat -A POSTROUTING --dst $LAN_IP -p tcp --dport $SRV_PORT -j SNAT --to-source $INT_IP
iptables -t nat -A POSTROUTING --dst 192.168.0.22 -p tcp --dport 80 -j SNAT --to-source 192.168.0.1
Если пакет предназначен веб-серверу, то обратный адрес клиента заменяется на внутренний адрес шлюза.
Этим мы гарантируем, что ответный пакет тоже пойдёт через шлюз.
Надо дополнительно отметить, что это правило важно только для внутренних клиентов. Ответ внешним клиентам пойдёт через шлюз в любом случае.
Но, пока что, для нормальной работы этого недостаточно. Предположим, что в качестве клиента выступает сам шлюз.
В соответствии с нашими предыдущими правилами он будет гонять трафик от себя к себе же и представлять исходящие пакеты транзитными. Так и с ума сойти недолго. Исправляем это:
iptables -t nat -A OUTPUT --dst $EXT_IP -p tcp --dport $SRV_PORT -j DNAT --to-destination $LAN_IP
iptables -t nat -A OUTPUT --dst 1.2.3.4 -p tcp --dport 80 -j DNAT --to-destination 192.168.0.22
Вот теперь - всё. Получившийся результат можно оформить в виде скрипта, чтобы не делать каждый раз всё вручную.
Кстати.
Если подключение к сети интернет осуществляется, например, через pppoe, то внешним интерфейсом будет pppN, он и должен быть вписан в правила iptables. Потому что в этом случае интерфейс eth0 будет использоваться только для установки связи с pppoe-сервером.
script.sh
#!/bin/bash
EXT_IP="xxx.xxx.xxx.xxx" # Он всё равно чаще всего один и тот же.
INT_IP="xxx.xxx.xxx.xxx" # См. выше.
EXT_IF=eth0 # Внешний и внутренний интерфейсы.
INT_IF=eth1 # Для шлюза они вряд ли изменятся, поэтому можно прописать вручную.
LAN_IP=$1   # Локальный адрес сервера передаём скрипту первым параметром,
SRV_PORT=$2 # а тип сервера, в смысле какой порт (или набор портов) открывать - вторым

# Здесь желательно сделать проверку ввода данных, потому что операции достаточно серьёзные.

iptables -t nat -A PREROUTING --dst $EXT_IP -p tcp --dport $SRV_PORT -j DNAT --to-destination $LAN_IP
iptables -t nat -A POSTROUTING --dst $LAN_IP -p tcp --dport $SRV_PORT -j SNAT --to-source $INT_IP
iptables -t nat -A OUTPUT --dst $EXT_IP -p tcp --dport $SRV_PORT -j DNAT --to-destination $LAN_IP
iptables -I FORWARD 1 -i $EXT_IF -o $INT_IF -d $LAN_IP -p tcp -m tcp --dport $SRV_PORT -j ACCEPT
Теперь, чтобы обеспечить доступ извне к локальному FTP по адресу 192.168.0.56, достаточно набрать в консоли от имени суперпользователя:
./script.sh 192.168.0.56 20,21
Экономия времени и сил налицо.

Перенаправление портов

Перенаправление портов нужно в том случае, если мы хотим «замаскировать» внутреннюю службу, обеспечив к ней доступ извне не по стандартному, а совсем по другому порту. Конечно, можно заставить сам веб-сервер слушать нестандартный порт, но если он используется рядовыми сотрудниками внутри локальной сети, то мы элементарно столкнёмся с человеческим фактором. Сотрудникам будет очень тяжело объяснить, что теперь для доступа к корпоративному сайту надо после его имени вводить набор цифр через двоеточие.
Именно из-за человеческого фактора перенаправление портов используется, в основном, специалистами, для удалённого администрирования.
Пусть $FAKE_PORT - обманный порт на внешнем интерфейсе шлюза, подключившись к которому мы должны попасть на адрес $LAN_IP и порт $SRV_PORT.
Набор правил для iptables будет отличаться несущественно, поэтому приведу сразу пример итогового скрипта для ленивых.
#!/bin/bash
EXT_IP="xxx.xxx.xxx.xxx" # Он всё равно чаще всего один и тот же.
INT_IP="xxx.xxx.xxx.xxx" # См. выше.
EXT_IF=eth0 # Внешний и внутренний интерфейсы.
INT_IF=eth1 # Для шлюза они вряд ли изменятся, поэтому можно прописать вручную.
FAKE_PORT=$1  # Вначале передаём скрипту "неправильный" порт на внешнем интерфейсе,
LAN_IP=$2     # затем - локальный адрес сервера
SRV_PORT=$3   # и в конце - реальный порт для подключения к серверу

# Здесь опять надо сделать проверку ввода данных, потому что операции всё ещё серьёзные.

iptables -t nat -A PREROUTING -d $EXT_IP -p tcp -m tcp --dport $FAKE_PORT -j DNAT --to-destination $LAN_IP:$SRV_PORT
iptables -t nat -A POSTROUTING -d $LAN_IP -p tcp -m tcp --dport $SRV_PORT -j SNAT --to-source $INT_IP
iptables -t nat -A OUTPUT -d $EXT_IP -p tcp -m tcp --dport $SRV_PORT -j DNAT --to-destination $LAN_IP
iptables -I FORWARD 1 -i $EXT_IF -o $INT_IF -d $LAN_IP -p tcp -m tcp --dport $SRV_PORT -j ACCEPT
По сути изменилась только первая строчка, поскольку только она отвечает за первичную обработку входящих пакетов. Дальше всё следует по стандартной процедуре таблиц и цепочек правил.
Изменения в остальных правилах сделаны для наглядности и их сути не меняют.

среда, 25 мая 2016 г.

Adjust for best performance via group policy (Windows desktop settings)

Add followed gegistry keys to your group policy.


[HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\VisualEffects]
;0 = Let Windows choose what's best for my computer
;1 = Adjust for best appearance
;2 = Adjust for best performance
;3 = Custom
"VisualFXSetting"=dword:00000003
[HKCU\Software\Microsoft\Windows\CurrentVersion\ThemeManager]
;Use visual styles on windows and buttons (0=off 1=on)
"ThemeActive"="1"
[HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced]
;Use common tasks in folders (0=off 1=on)
"WebView"=dword:00000001
;Show translucent selection rectangle (0=off 1=on)
"ListviewAlphaSelect"=dword:00000001
;Use drop shadows for icon labels on the desktop (0=off 1=on)
"ListviewShadow"=dword:00000001
;Use a background image for each folder type (0=off 1=on)
"ListviewWatermark"=dword:00000001
;Slide taskbar buttons (0=off 1=on)
"TaskbarAnimations"=dword:00000001
[HKCU\Control Panel\Desktop\WindowMetrics]
;Animate windows when minimizing and maximizing (0=off 1=on)
"MinAnimate"="1"
[HKCU\Control Panel\Desktop]
;Show window contents while dragging (0=off 1=on)
"DragFullWindows"="1"
;Smooth edges of screen fonts (0=off 2=on)
"FontSmoothing"="2"
;Smooth scroll list boxes
;Slide open combo boxes
;Fade or slide menus into view
;Show shadows under mouse pointer
;Fade or slide tooltips into view
;Fade out menu items after clicking
;Show shadows under menus
;(All off = 90,12,01,80   All on = 9e,3e,05,80)
"UserPreferencesMask"=hex:9e,3e,05,80

пятница, 29 апреля 2016 г.

Bacula Heartbeat Interval

Источник

При использовании резервного копирования Bacula вылезает ньюанс, если между Director-сервером и FD-сервером (клиентом) находится маршрутизатор (используется NAT) - выполняемая задача (job) может вдруг ни с того, ни с сего остановиться с ошибкой "Fatal error: Network error with FD during Backup: ERR=Connection reset by peer".
Дело всё в том, что Director, инициируя задачу на клиенте, в процессе выполнения просто ждёт - весь трафик идёт между FD-сервером (клиентом) и SD-сервером (storage). Маршрутизатор спустя установленное время (timeout, у cisco - 7200 секунд) решив, что соединение между Director-сервером и FD-сервером (клиентом) умерло, просто удаляет информацию о соединении из своей таблицы соединений, обрывая таким образом выполняемую задачу.
Решается проблема тривиально - на FD-сервере (клиенте) в конфигурационном файле в секцию FileDaemon добавить:

Heartbeat Interval = 60
 
При действующем Heartbeat-интервале FD-сервер в процессе выполнения работы пересылает heartbeat-пакеты Director-серверу, создавая таким образом активность в соединении и маршрутизатор, видя, что соединение "живо", не вмешивается.

Ссылки:
  1. Client/File daemon Configuration
  2. Timeout (?) problems with some Full backups
Из официального FAQ Bacula project:


My backup starts, but dies after a while with "Connection reset by peer" error

This is usually due to some router/firewall having a connection timeout, and it kills connections that are “idle” for too long. To fix, you should do both of:
(1) activate keepalive by adding
 Heartbeat Interval = 60
in all of SD, FD and DIR configurations. Note that by itself this still won't be enough if you have some slow operations like SQL queries, accurate backups enabled, etc. You need the second point too.
(2) lower the system time before keepalives are sent
Setting the system SO_KEEPALIVE timeouts is needed as the defaults might be quite long (like 2 hours of inactivity or even longer before system starts to send keepalives). See http://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/ for instructions for GNU/Linux systems, or some other systems at http://www.gnugk.org/keepalive.html or http://www.starquest.com/Supportdocs/techStarLicense/SL002_TCPKeepAlive.shtml
You can check if SO_KEEPALIVE timeout is setup correctly by restarting bacula and starting a new job, and then check the current state of TCP connections with “netstat -to”. Here is how it looks when it is WRONG and needs fixing (this example shows it will not start sending keepalives for about 7200 seconds, that is 2 hours!):
# netstat -to
tcp        0      0 client:9102       server:54043      ESTABLISHED  keepalive (7196.36/0/0)
tcp        0      0 client:43628      server:9103       ESTABLISHED  keepalive (7197.26/0/0)
In that case you can try setting the system defaults to lower value, for example on GNU/Linux systems (or check URLs above for other systems) with:
sysctl -w net.ipv4.tcp_keepalive_time=60
Put that in /etc/sysctl.conf or /etc/sysctl.d/* to keep it across reboots.
Alternatively, one could try to increase router/firewall timeouts and/or number of simultaneous connections, and/or reduce time needed for backup (turning off accurate backups, reducing filesets, etc) or reducing the time network connection is idle during backup (for example, running Full backup instead of Incremental will take longer time, but the network connection will be idle for much less time, as bacula won't have to check if files have changed, which can take some time).
Some routers/firewalls (those having connection tracking / stateful firewall / NAT capabilities) will also reset all running connections if they reboot. Not much helping here, apart from avoiding condition which may make them reboot, or turning off their connection tracking / firewall / NAT (which might make them useless, of course)

четверг, 28 апреля 2016 г.

Памятка пользователям ssh

Источник

abstract: В статье описаны продвинутые функций OpenSSH, которые позволяют сильно упростить жизнь системным администраторам и программистам, которые не боятся шелла. В отличие от большинства руководств, которые кроме ключей и -L/D/R опций ничего не описывают, я попытался собрать все интересные фичи и удобства, которые с собой несёт ssh.

Предупреждение: пост очень объёмный, но для удобства использования я решил не резать его на части.

Оглавление:

  • управление ключами
  • копирование файлов через ssh
  • Проброс потоков ввода/вывода
  • Монтирование удалённой FS через ssh
  • Удалённое исполнение кода
  • Алиасы и опции для подключений в .ssh/config
  • Опции по-умолчанию
  • Проброс X-сервера
  • ssh в качестве socks-proxy
  • Проброс портов — прямой и обратный
  • Реверс-сокс-прокси
  • туннелирование L2/L3 трафика
  • Проброс агента авторизации
  • Туннелирование ssh через ssh сквозь недоверенный сервер (с большой вероятностью вы этого не знаете)

Управление ключами


Теория в нескольких словах: ssh может авторизоваться не по паролю, а по ключу. Ключ состоит из открытой и закрытой части. Открытая кладётся в домашний каталог пользователя, «которым» заходят на сервер, закрытая — в домашний каталог пользователя, который идёт на удалённый сервер. Половинки сравниваются (я утрирую) и если всё ок — пускают. Важно: авторизуется не только клиент на сервере, но и сервер по отношению к клиенту (то есть у сервера есть свой собственный ключ). Главной особенностью ключа по сравнению с паролем является то, что его нельзя «украсть», взломав сервер — ключ не передаётся с клиента на сервер, а во время авторизации клиент доказывает серверу, что владеет ключом (та самая криптографическая магия).

Генерация ключа


Свой ключ можно сгенерировать с помощью команды ssh-keygen. Если не задать параметры, то он сохранит всё так, как надо.

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

Сменить пароль на ключ можно с помощью команды ssh-keygen -p.

Структура ключа


(если на вопрос про расположение ответили по-умолчанию).
~/.ssh/id_rsa.pub — открытый ключ. Его копируют на сервера, куда нужно получить доступ.
~/.ssh/id_rsa — закрытый ключ. Его нельзя никому показывать. Если вы в письмо/чат скопипастите его вместо pub, то нужно генерировать новый ключ. (Я не шучу, примерно 10% людей, которых просишь дать ssh-ключ постят id_rsa, причём из этих десяти процентов мужского пола 100%).

Копирование ключа на сервер


В каталоге пользователя, под которым вы хотите зайти, если создать файл ~/.ssh/authorized_keys и положить туда открытый ключ, то можно будет заходить без пароля. Обратите внимание, права на файл не должны давать возможность писать в этот файл посторонним пользователям, иначе ssh его не примет. В ключе последнее поле — user@machine. Оно не имеет никакого отношения к авторизации и служит только для удобства определения где чей ключ. Заметим, это поле может быть поменяно (или даже удалено) без нарушения структуры ключа.

Если вы знаете пароль пользователя, то процесс можно упростить. Команда ssh-copy-id user@server позволяет скопировать ключ не редактируя файлы вручную.

Замечание: Старые руководства по ssh упоминают про authorized_keys2. Причина: была первая версия ssh, потом стала вторая (текущая), для неё сделали свой набор конфигов, всех это очень утомило, и вторая версия уже давным давно переключилась на версии без всяких «2». То есть всегда authorized_keys и не думать о разных версиях.

Если у вас ssh на нестандартном порту, то ssh-copy-id требует особого ухищрения при работе: ssh-copy-id '-p 443 user@server' (внимание на кавычки).

Ключ сервера


Первый раз, когда вы заходите на сервер, ssh вас спрашивает, доверяете ли вы ключу. Если отвечаете нет, соединение закрывается. Если да — ключ сохраняется в файл ~/.ssh/known_hosts. Узнать, где какой ключ нельзя (ибо несекьюрно).

Если ключ сервера поменялся (например, сервер переустановили), ssh вопит от подделке ключа. Обратите внимание, если сервер не трогали, а ssh вопит, значит вы не на тот сервер ломитесь (например, в сети появился ещё один компьютер с тем же IP, особо этим страдают всякие локальные сети с 192.168.1.1, которых в мире несколько миллионов). Сценарий «злобной man in the middle атаки» маловероятен, чаще просто ошибка с IP, хотя если «всё хорошо», а ключ поменялся — это повод поднять уровень паранойи на пару уровней (а если у вас авторизация по ключу, а сервер вдруг запросил пароль — то паранойю можно включать на 100% и пароль не вводить).

Удалить известный ключ сервера можно командой ssh-keygen -R server. При этом нужно удалить ещё и ключ IP (они хранятся раздельно): ssh-keygen -R 127.0.0.1.

Ключ сервера хранится в /etc/ssh/ssh_host_rsa_key и /etc/ssh/ssh_host_rsa_key.pub. Их можно:
а) скопировать со старого сервера на новый.
б) сгенерировать с помощью ssh-keygen. Пароля при этом задавать не надо (т.е. пустой). Ключ с паролем ssh-сервер использовать не сможет.

Заметим, если вы сервера клонируете (например, в виртуалках), то ssh-ключи сервера нужно обязательно перегенерировать.

Старые ключи из know_hosts при этом лучше убрать, иначе ssh будет ругаться на duplicate key.


Копирование файлов


Передача файлов на сервер иногда может утомлять. Помимо возни с sftp и прочими странными вещами, ssh предоставляет нам команду scp, которая осуществляет копирование файла через ssh-сессию.

scp path/myfile user@8.8.8.8:/full/path/to/new/location/


Обратно тоже можно:
scp user@8.8.8.8:/full/path/to/file /path/to/put/here


Fish warning: Не смотря на то, что mc умеет делать соединение по ssh, копировать большие файлы будет очень мучительно, т.к. fish (модуль mc для работы с ssh как с виртуальной fs) работает очень медленно. 100-200кб — предел, дальше начинается испытание терпения. (Я вспомнил свою очень раннюю молодость, когда не зная про scp, я копировал ~5Гб через fish в mc, заняло это чуть больше 12 часов на FastEthernet).

Возможность копировать здорово. Но хочется так, чтобы «сохранить как» — и сразу на сервер. И чтобы в графическом режиме копировать не из специальной программы, а из любой, привычной.

Так тоже можно:

sshfs


Теория: модуль fuse позволяет «экспортировать» запросы к файловой системе из ядра обратно в userspace к соответствующей программе. Это позволяет легко реализовывать «псевдофайловые системы». Например, мы можем предоставить доступ к удалённой файловой системе через ssh так, что все локальные приложения (за малым исключением) не будут ничего подозревать.

Собственно, исключение: O_DIRECT не поддерживается, увы (это проблема не sshfs, это проблема fuse вообще).

Использование: установить пакет sshfs (сам притащит за собой fuse).

Собственно, пример моего скрипта, который монтирует desunote.ru (размещающийся у меня на домашнем комьютере — с него в этой статье показываются картинки) на мой ноут:

#!/bin/bash
sshfs desunote.ru:/var/www/desunote.ru/ /media/desunote.ru -o reconnect


Делаем файл +x, вызываем, идём в любое приложение, говорим сохранить и видим:



Параметры sshfs, которые могут оказаться важными: -o reconnect (говорит пытаться пересоединиться вместо ошибок).

Если вы много работаете с данными от рута, то можно (нужно) сделать idmap:

-o idmap=user. Работает она следующим образом: если мы коннектимся как пользователь pupkin@server, а локально работаем как пользователь vasiliy, то мы говорим «считать, что файлы pupkin, это файлы vasiliy». ну или «root», если мы коннектимся как root.

В моём случае idmap не нужен, так как имена пользователей (локальное и удалённое) совпадают.

Заметим, комфортно работать получается только если у нас есть ssh-ключик (см. начало статьи), если нет — авторизация по паролю выбешивает на 2-3 подключение.

Отключить обратно можно командой fusermount -u /path, однако, если соединение залипло (например, нет сети), то можно/нужно делать это из-под рута: sudo umount -f /path.



Удалённое исполнение кода


ssh может выполнить команду на удалённом сервере и тут же закрыть соединение. Простейший пример:

ssh user@server ls /etc/


Выведет нам содержимое /etc/ на server, при этом у нас будет локальная командная строка.

Некоторые приложения хотят иметь управляющий терминал. Их следует запускать с опцией -t:
ssh user@server -t remove_command


Кстати, мы можем сделать что-то такого вида:
ssh user@server cat /some/file|awk '{print $2}' |local_app


Это нас приводит следующей фиче:

Проброс stdin/out


Допустим, мы хотим сделать запрос к программе удалённо, а потом её вывод поместить в локальный файл

ssh user@8.8.8.8 command >my_file

Допустим, мы хотим локальный вывод положить удалённо

mycommand |scp — user@8.8.8.8:/path/remote_file

Усложним пример — мы можем прокидывать файлы с сервера на сервер: Делаем цепочку, чтобы положить stdin на 10.1.1.2, который нам не доступен снаружи:

mycommand | ssh user@8.8.8.8 «scp — user@10.1.1.2:/path/to/file»

Есть и вот такой головоломный приём использования pipe'а (любезно подсказали в комментариях в жж):

tar -c * | ssh user@server "cd && tar -x"


Tar запаковывает файлы по маске локально, пишет их в stdout, откуда их читает ssh, передаёт в stdin на удалённом сервере, где их cd игнорирует (не читает stdin), а tar — читает и распаковывает. Так сказать, scp для бедных.

Алиасы


Скажу честно, до последнего времени не знал и не использовал. Оказались очень удобными.

В более-менее крупной компании часто оказывается, что имена серверов выглядят так: spb-MX-i3.extrt.int.company.net. И пользователь там не равен локальному. То есть логиниться надо так: ssh ivanov_i@spb-MX-i3.extrt.int.company.net. Каждый раз печатать — туннельных синдромов не напасёшься. В малых компаниях проблема обратная — никто не думает о DNS, и обращение на сервер выглядит так: ssh root@192.168.1.4. Короче, но всё равно напрягает. Ещё большая драма, если у нас есть нестандартный порт, и, например, первая версия ssh (привет цискам). Тогда всё выглядит так: ssh -1 -p 334 vv_pupkin@spb-MX-i4.extrt.int.company.net. Удавиться. Про драму с scp даже рассказывать не хочется.

Можно прописать общесистемные alias'ы на IP (/etc/hosts), но это кривоватый выход (и пользователя и опции всё равно печатать). Есть путь короче.

Файл ~/.ssh/config позволяет задать параметры подключения, в том числе специальные для серверов, что самое важное, для каждого сервера своё. Вот пример конфига:

Host ric
        Hostname ооо-рога-и-копыта.рф
        User Администратор
        ForwardX11 yes
        Compression yes
Host home
        Hostname myhome.dyndns.org
        User vasya
        PasswordAuthentication no


Все доступные для использования опции можно увидеть в man ssh_config (не путать с sshd_config).


Опции по умолчанию


По подсказке UUSER: вы можете указать настройки соединения по умолчанию с помощью конструкции Host *, т.е., например:

Host *
User root
Compression yes


То же самое можно сделать и в /etc/ssh/ssh_config (не путать с /etc/ssh/sshd_config), но это требует прав рута и распространяется на всех пользователей.




Проброс X-сервера


Собственно, немножко я проспойлерил эту часть в примере конфига выше. ForwardX11 — это как раз оно.

Теория: Графические приложения в юникс обычно используют X-сервер (wayland в пути, но всё ещё не готов). Это означает, что приложение запускается и подключается к X-серверу для рисования. Иными словами, если у вас есть голый сервер без гуя и есть локальный x-сервер (в котором вы работаете), то вы можете дать возможность приложениям с сервера рисовать у вас на рабочем столе. Обычно подключение к удалённом X-серверу — не самая безопасная и тривиальная вещь. SSH позволяет упростить этот процесс и сделать его совсем безопасным. А возможность жать трафик позволяет ещё и обойтись меньшим трафиком (т.е. уменьшить утилизацию канала, то есть уменьшить ping (точнее, latency), то есть уменьшить лаги).

Ключики: -X — проброс X-сервера. -Y проброс авторизации.

Достаточно просто запомнить комбинацию ssh -XYC user@SERVER.
В примере выше (названия компании вымышленные) я подключаюсь к серверу ооо-рога-и-копыта.рф не просто так, а с целью получить доступ к windows-серверу. Безопасность microsoft при работе в сети мы все хорошо знаем, так что выставлять наружу голый RDP неуютно. Вместо этого мы подключаемся к серверу по ssh, а дальше запускаем там команду rdesktop:
ssh ric
rdesktop -k en-us 192.168.1.1 -g 1900x1200


и чудо, окошко логина в windows на нашем рабочем столе. Заметим, тщательно зашифрованное и неотличимое от обычного ssh-трафика.




Socks-proxy


Когда я оказываюсь в очередной гостинице (кафе, конференции), то местный wifi чаще всего оказывается ужасным — закрытые порты, неизвестно какой уровень безопасности. Да и доверия к чужим точкам доступа не особо много (это не паранойя, я вполне наблюдал как уводят пароли и куки с помощью банального ноутбука, раздающего 3G всем желающим с названием близлежащей кафешки (и пишущего интересное в процессе)).

Особые проблемы доставляют закрытые порты. То джаббер прикроют, то IMAP, то ещё что-нибудь.

Обычный VPN (pptp, l2tp, openvpn) в таких ситуациях не работает — его просто не пропускают. Экспериментально известно, что 443ий порт чаще всего оставляют, причём в режиме CONNECT, то есть пропускают «как есть» (обычный http могут ещё прозрачно на сквид завернуть).

Решением служит socks-proxy режим работы ssh. Его принцип: ssh-клиент подключается к серверу и слушает локально. Получив запрос, он отправляет его (через открытое соединение) на сервер, сервер устанавливает соединение согласно запросу и все данные передаёт обратно ssh-клиенту. А тот отвечает обратившемуся. Для работы нужно сказать приложениям «использовать socks-proxy». И указать IP-адрес прокси. В случае с ssh это чаще всего localhost (так вы не отдадите свой канал чужим людям).

Подключение в режиме sock-proxy выглядит так:
ssh -D 8080 user@server


В силу того, что чужие wifi чаще всего не только фиговые, но и лагливые, то бывает неплохо включить опцию -C (сжимать трафик). Получается почти что opera turbo (только картинки не жмёт). В реальном сёрфинге по http жмёт примерно в 2-3 раза (читай — если вам выпало несчастье в 64кбит, то вы будете мегабайтные страницы открывать не по две минуты, а секунд за 40. Фигово, но всё ж лучше). Но главное: никаких украденных кук и подслушанных сессий.

Я не зря сказал про закрытые порты. 22ой порт закрывают ровно так же, как «не нужный» порт джаббера. Решение — повесить сервер на 443-й порт. Снимать с 22 не стоит, иногда бывают системы с DPI (deep packet inspection), которые ваш «псевдо-ssl» не пустят.

Вот так выглядит мой конфиг:

/etc/ssh/sshd_config:
(фрагмент)
Port 22
Port 443

А вот кусок ~/.ssh/config с ноутбука, который описывает vpn

Host vpn
    Hostname desunote.ru
    User vasya
    Compression yes
    DynamicForward 127.1:8080
    Port 443


(обратите внимание на «ленивую» форму записи localhost — 127.1, это вполне себе законный метод написать 127.0.0.1)



Проброс портов


Мы переходим к крайне сложной для понимания части функционала SSH, позволяющей осуществлять головоломные операции по туннелированию TCP «из сервера» и «на сервер».

Для понимания ситуации все примеры ниже будут ссылаться на вот эту схему:



Комментарии: Две серые сети. Первая сеть напоминает типичную офисную сеть (NAT), вторая — «гейтвей», то есть сервер с белым интерфейсом и серым, смотрящим в свою собственную приватную сеть. В дальнейших рассуждениях мы полагаем, что «наш» ноутбук — А, а «сервер» — Б.

Задача: у нас локально запущено приложение, нам нужно дать возможность другому пользователю (за пределами нашей сети) посмотреть на него.

Решение: проброс локального порта (127.0.0.1:80) на публично доступный адрес. Допустим, наш «публично доступный» Б занял 80ый порт чем-то полезным, так что пробрасывать мы будем на нестандартный порт (8080).

Итоговая конфигурация: запросы на 8.8.8.8:8080 будут попадать на localhost ноутбука А.

ssh -R 127.1:80:8.8.8.8:8080 user@8.8.8.8


Опция -R позволяет перенаправлять с удалённого (Remote) сервера порт на свой (локальный).
Важно: если мы хотим использовать адрес 8.8.8.8, то нам нужно разрешить GatewayPorts в настройках сервера Б.
Задача. На сервере «Б» слушает некий демон (допустим, sql-сервер). Наше приложение не совместимо с сервером (другая битность, ОС, злой админ, запрещающий и накладывающий лимиты и т.д.). Мы хотим локально получить доступ к удалённому localhost'у.

Итоговая конфигурация: запросы на localhost:3333 на 'A' должны обслуживаться демоном на localhost:3128 'Б'.

ssh -L 127.1:3333:127.1:3128 user@8.8.8.8


Опция -L позволяет локальные обращения (Local) направлять на удалённый сервер.

Задача: На сервере «Б» на сером интерфейсе слушает некий сервис и мы хотим дать возможность коллеге (192.168.0.3) посмотреть на это приложение.

Итоговая конфигурация: запросы на наш серый IP-адрес (192.168.0.2) попадают на серый интерфейс сервера Б.

ssh -L 192.168.0.2:8080:10.1.1.1:80 user@8.8.8.8


Вложенные туннели


Разумеется, туннели можно перенаправлять.

Усложним задачу: теперь нам хочется показать коллеге приложение, запущенное на localhost на сервере с адресом 10.1.1.2 (на 80ом порту).

Решение сложно:
ssh -L 192.168.0.2:8080:127.1:9999 user@8.8.8.8 ssh -L 127.1:9999:127.1:80 user2@10.1.1.2


Что происходит? Мы говорим ssh перенаправлять локальные запросы с нашего адреса на localhost сервера Б и сразу после подключения запустить ssh (то есть клиента ssh) на сервере Б с опцией слушать на localhost и передавать запросы на сервер 10.1.1.2 (куда клиент и должен подключиться). Порт 9999 выбран произвольно, главное, чтобы совпадал в первом вызове и во втором.

Реверс-сокс-прокси



Если предыдущий пример вам показался простым и очевидным, то попробуйте догадаться, что сделает этот пример:
ssh -D 8080 -R 127.1:8080:127.1:8080 user@8.8.8.8 ssh -R 127.1:8080:127.1:8080 user@10.1.1.2

Если вы офицер безопасности, задача которого запретить использование интернета на сервере 10.1.1.2, то можете начинать выдёргивать волосы на попе, ибо эта команда организует доступ в интернет для сервера 10.1.1.2 посредством сокс-прокси, запущенного на компьютере «А». Трафик полностью зашифрован и неотличим от любого другого трафика SSH. А исходящий трафик с компьютера с точки зрения сети «192.168.0/24» не отличим от обычного трафика компьютера А.


Туннелирование


Если к этому моменту попа отдела безопасности не сияет лысиной, а ssh всё ещё не внесён в список врагов безопасности номер один, вот вам окончательный убийца всего и вся: туннелирование IP или даже ethernet. В самых радикальных случаях это позволяет туннелировать dhcp, заниматься удалённым arp-спуфингом, делать wake up on lan и прочие безобразия второго уровня.

Подробнее описано тут: www.khanh.net/blog/archives/51-using-openSSH-as-a-layer-2-ethernet-bridge-VPN.html

(сам я увы, таким не пользовался).

Легко понять, что в таких условиях невозможно никаким DPI (deep packet inspection) отловить подобные туннели — либо ssh разрешён (читай — делай что хочешь), либо ssh запрещён (и можно смело из такой компании идиотов увольняться не ощущая ни малейшего сожаления).

Проброс авторизации


Если вы думаете, что на этом всё, то…… впрочем, в отличие от автора, у которого «снизу» ещё не написано, читатель заранее видит, что там снизу много букв и интриги не получается.

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

Для начала о простом пробросе авторизации.

Повторю картинку:



Допустим, мы хотим подключиться к серверу 10.1.1.2, который готов принять наш ключ. Но копировать его на 8.8.8.8 мы не хотим, ибо там проходной двор и половина людей имеет sudo и может шариться по чужим каталогам. Компромиссным вариантом было бы иметь «другой» ssh-ключ, который бы авторизовывал user@8.8.8.8 на 10.1.1.2, но если мы не хотим пускать кого попало с 8.8.8.8 на 10.1.1.2, то это не вариант (тем паче, что ключ могут не только поюзать, но и скопировать себе «на чёрный день»).

ssh предлагает возможность форварда ssh-агента (это такой сервис, который запрашивает пароль к ключу). Опция ssh -A пробрасывает авторизацию на удалённый сервер.

Вызов выглядит так:

ssh -A user@8.8.8.8 ssh user2@10.1.1.2


Удалённый ssh-клиент (на 8.8.8.8) может доказать 10.1.1.2, что мы это мы только если мы к этому серверу подключены и дали ssh-клиенту доступ к своему агенту авторизации (но не ключу!).

В большинстве случаев это прокатывает.

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

Есть ещё более могучий метод — он превращает ssh в простой pipe (в смысле, «трубу») через которую насквозь мы осуществляем работу с удалённым сервером.

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

Эту клёвую настройку я не знал, и раскопал её redrampage.

Настройка завязана на две возможности ssh: опцию -W (превращающую ssh в «трубу») и опцию конфига ProxyCommand (опции командной строки, вроде бы нет), которая говорит «запустить программу и присосаться к её stdin/out». Опции эти появились недавно, так что пользователи centos в пролёте.

Выглядит это так (циферки для картинки выше):

.ssh/config:
Host raep
     HostName 10.1.1.2
     User user2
     ProxyCommand ssh -W %h:%p user@8.8.8.8


Ну а подключение тривиально: ssh raep.

Повторю важную мысль: сервер 8.8.8.8 не может перехватить или подделать трафик, воспользоваться агентом авторизации пользователя или иным образом изменить трафик. Запретить — да, может. Но если разрешил — пропустит через себя без расшифровки или модификации. Для работы конфигурации нужно иметь свой открытый ключ в authorized_keys как для user@8.8.8.8, так и в user2@10.1.1.2

Разумеется, подключение можно оснащать всеми прочими фенечками — прокидыванием портов, копированием файлов, сокс-прокси, L2-туннелями, туннелированием X-сервера и т.д.