Bash Days | Linux | DevOps
23.3K subscribers
157 photos
24 videos
679 links
Авторский канал от действующего девопса

Самобытно про разработку, devops, linux, скрипты, сисадминство, техдирство и за айтишную жизу.

Автор: Роман Шубин
Реклама: @maxgrue

MAX: https://max.ru/bashdays

Курс: @tormozilla_bot
Блог: https://bashdays.ru
Download Telegram
Здрасти, сегодня продолжаем издеваться над ssh.

Давай прикрутим 2FA.

Идем на сервер к которому хотим подключmся по ssh и ставим пакеты:

sudo apt update
sudo apt install libpam-google-authenticator


Запускаем конфигуратор:

google-authenticator


Я запускаю под рутом, но если тебе нужно настроить 2FA для другого юзера, для начала переключись на этого пользователя и только потом запускай конфигуратор.

После запуска конфигуратора, получишь по ебалу:

Do you want authentication tokens to be time-based (y/n)


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

Можно еще всякие ключики использовать:

google-authenticator -t -f -d -w 3 -e 5 -r 3 -R 60


Если интересно: google-authenticator --help

Всю эту инфу куданить себе скопируй чтоб не проебаться.

Дальше сканируем этот QR код, либо берем секретный ключ который он тебе выплюнул и вставляем в vaultwarden в TOTP или на телефоне в апку добавляем.

Тот самый секретный ключ:

Your new secret key is: MAIY4KDCXKWHPDCI


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

После этого оно выплюнет тебе рекавери коды, ну и спросит:

Do you want me to update your "/root/.google_authenticator" file?

Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks

и другие


На всё соглашаешься, но если хочешь, можешь прочитать и тонко затюнить под свои задачи.

В файл /root/.google_authenticator сохранится секретный ключ и коды восстановления. Этот файл не трогаем, без него тоже нихуя не заработает.

Теперь открываем файл /etc/pam.d/sshd

И добавляем в него строчку:

# @include common-auth
auth required pam_google_authenticator.so


По необходимости комментим common-auth если ничего не работает. Есть вариант не комментить, но тогда нужно правильно настроить common-auth, но у нас сегодня не про это.

Закомментировав этот модуль ты отключаешь стандартные механизмы аутентификации и даешь зеленый свет на использование pam_google_authenticator.

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

Дальше добавляем в конфиг: /etc/ssh/sshd_config

UsePAM yes
PasswordAuthentication no
ChallengeResponseAuthentication yes
PubkeyAuthentication yes
AuthenticationMethods publickey,keyboard-interactive


Вот и всё, настройка 2FA завершена.

Рестартим:

sudo systemctl restart ssh


И пробуем подключиться по ssh к этому серверу:

ssh root@bashdays.ru

(root@bashdays.ru) Verification code:


Ха! А что вводить? Это и есть 2FA, сюда вводим одноразовый код который выплюнул тебе vaultwarden либо аппка на телефоне.

Всё! Залетаем спокойно на сервер. Без кода и ключа хуй ты теперь чо сделаешь.

Как использовать резервные коды?

Да также при запросе в Verification code. НО из файла /root/.google_authenticator они будут отлетать. Тут тоже аккуратнее.

Также можешь включать 2FA для конкретных пользователей, в конфиге /etc/ssh/sshd_config

Match User <имя юзера>
AuthenticationMethods publickey,keyboard-interactive


Настроек там жопой кушай, я тебе лишь концепт показал как эту хуйню можно быстренько настроить.

А как работать с 2FA и QR кодами из консоли, можешь почитать тут.


Главное не спеши и делай всё вдумчиво, чтобы не проебать доступ к серверу. Ну а если все проебал, да и хуй с ним, ебани кофейка и мультики посмотри.

tags: #linux #devops #linuxfactory

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
67
Ребята с LF порой интересуются — а нахуя в nginx нужна поддержка lua? Можно какой-то пример, но только не Hello World?

Конечно можно!

Понадобилось мне как-то реализовать продвинутый basic auth, чтобы nginx сходил в mysql базу и сопоставил введенные учетные данные.

А как блядь это сделать?

Тут-то и пригодится Lua!

Для начала создаем базу (nginx_auth) и табличку users. Ну и в ней колонки username и password. В username храним имя пользователя, в password захэшированный пароль:

SHA1('$UpperPa$$word')


Эту команду выполняешь в mysql, в ответ он выплюнет тебе хэш, его и нужно будет заебенить в колонку password.

Дальше конфигуряем nginx:

    location / {
content_by_lua_file /etc/nginx/lua/auth.lua;
}

location @authenticated {
root /var/www/bashdays/htdocs/site;
index index.html;
}


В nginx само собой добавляем модуль Lua, Как его собрать можешь в гугле посмотреть, ну либо взять какойнить openresty.


Ну и сам скрипт кидаем в /etc/nginx/lua/auth.lua;

local mysql = require "resty.mysql"
local sha1 = require "resty.sha1"
local resty_string = require "resty.string"
local db, err = mysql:new()

-- Установка таймаута
if not db then
ngx.log(ngx.ERR, "failed to create mysql object: ", err)
return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end

db:set_timeout(1000)

-- Подключение к базе данных
local res, err = db:connect{
host = "db",
port = 3306,
database = "nginx_auth",
user = "nginx_user",
password = "password",
charset = "utf8",
}

if not res then
ngx.log(ngx.ERR, "failed to connect to MySQL: ", err)
return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end

-- Извлекаем данные из заголовков Authorization
local auth = ngx.var.http_authorization

if not auth or not auth:find("Basic ") then
ngx.header["WWW-Authenticate"] = 'Basic realm="Restricted Area"'
return ngx.exit(ngx.HTTP_UNAUTHORIZED)
end

-- Парсим Basic Auth заголовок
local encoded = auth:sub(7) -- Убираем "Basic " из начала
local decoded = ngx.decode_base64(encoded)

if not decoded then
ngx.header["WWW-Authenticate"] = 'Basic realm="Restricted Area"'
return ngx.exit(ngx.HTTP_UNAUTHORIZED)
end

-- Разделяем строку на имя пользователя и пароль
local username, password = decoded:match("([^:]+):(.+)")

if not username or not password then
ngx.header["WWW-Authenticate"] = 'Basic realm="Restricted Area"'
return ngx.exit(ngx.HTTP_UNAUTHORIZED)
end

-- Хешируем пароль
local sha1_obj = sha1:new()
sha1_obj:update(password)
local password_hash = resty_string.to_hex(sha1_obj:final())

-- Проверяем пользователя и пароль в базе данных
local sql = string.format("SELECT * FROM users WHERE username = '%s' AND password = '%s'", username, password_hash)
local res, err = db:query(sql)

if not res or #res == 0 then
ngx.header["WWW-Authenticate"] = 'Basic realm="Restricted Area"'
return ngx.exit(ngx.HTTP_UNAUTHORIZED)
end

-- Передаем управление Nginx для загрузки страницы
ngx.exec("@authenticated")


Всё! Релоадим nginx и получаем прокаченный Basic Auth.

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


Теперь nginx лезет в базу и при успешном исходе кидает пользователя в локейшен @authenticated.

Да, скрипт работает на mariadb. Для всяких перкон и т.п. возможно нужно будет переделать SELECT.

Вот такие пироги, вот тебе и заебачее применение Lua!

➡️ Кстати, если увидел вектор атаки, поделись в комментах.

tags: #linux #devops #lua #nginx

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
46