Compare commits
4 Commits
b0913ab7ef
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| 8597a75abb | |||
| 81f4ea764e | |||
| 39cf9e83e3 | |||
| aecd708bb5 |
@@ -49,7 +49,7 @@ Filesystem Inodes IUsed IFree IUse% Mounted on
|
|||||||
/dev/mapper/vg02-opt 262141952 486209 261655743 1% /opt
|
/dev/mapper/vg02-opt 262141952 486209 261655743 1% /opt
|
||||||
```
|
```
|
||||||
|
|
||||||
Деталь, которая зацепила взгляд: всего 67424 инода на 29-гигабайтном томе - по привычке принял это за фиксированное значение, заданное при создании файловой системы, как это работает в ext4. При 99% занятости с таким скромным лимitom легко вылететь по инодам даже без аномального количества файлов. Отложил мысль на потом - и, как выяснится в финале статьи, отложил с неверной гипотезой в основе.
|
Деталь, которая зацепила взгляд: всего 67424 инода на 29-гигабайтном томе - по привычке принял это за фиксированное значение, заданное при создании файловой системы, как это работает в ext4. При 99% занятости с таким скромным лимитом легко вылететь по инодам даже без аномального количества файлов. Отложил мысль на потом - и, как выяснится в финале статьи, отложил с неверной гипотезой в основе.
|
||||||
|
|
||||||
## Первая ошибка: du без -x
|
## Первая ошибка: du без -x
|
||||||
|
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ Ubuntu 24.04 хранит конфигурацию SSH в `/etc/ssh/sshd_config.
|
|||||||
Создай файл с настройками:
|
Создай файл с настройками:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo nano /etc/ssh/sshd_config.d/99-hardening.conf
|
sudo nano /etc/ssh/sshd_config.d/00-hardening.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -297,6 +297,8 @@ AcceptEnv LANG LC_*
|
|||||||
AddressFamily inet
|
AddressFamily inet
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Важно:** Ubuntu 24.04 хранит файлы конфигурации SSH в `/etc/ssh/sshd_config.d/` и применяет **первое** вхождение каждой директивы. Облачные образы Ubuntu часто поставляются с файлом `50-cloud-init.conf` который содержит `PasswordAuthentication yes` - он загружается раньше `99-hardening.conf` и его значение побеждает. Файл `00-hardening.conf` загружается первым и корректно перекрывает дефолты cloud-init.
|
||||||
|
|
||||||
**Важно:** Ubuntu 24.04 использует socket-активацию через `ssh.socket` - порт слушает не sshd напрямую, а сокет-юнит. Обычный `systemctl restart ssh` перезапускает только сервис, порт остаётся прежним. Для применения нового порта нужно перезапускать именно сокет.
|
**Важно:** Ubuntu 24.04 использует socket-активацию через `ssh.socket` - порт слушает не sshd напрямую, а сокет-юнит. Обычный `systemctl restart ssh` перезапускает только сервис, порт остаётся прежним. Для применения нового порта нужно перезапускать именно сокет.
|
||||||
|
|
||||||
**КРИТИЧНО:** Перед перезапуском открой вторую сессию и не закрывай её.
|
**КРИТИЧНО:** Перед перезапуском открой вторую сессию и не закрывай её.
|
||||||
@@ -331,7 +333,7 @@ LISTEN 0 4096 0.0.0.0:2222
|
|||||||
sudo systemctl cat ssh.socket
|
sudo systemctl cat ssh.socket
|
||||||
```
|
```
|
||||||
|
|
||||||
Строка `ListenStream=0.0.0.0:2222` подтверждает что порт применился.
|
Строка `ListenStream=2222` подтверждает что порт применился.
|
||||||
|
|
||||||
В новом терминале проверь подключение:
|
В новом терминале проверь подключение:
|
||||||
|
|
||||||
@@ -356,7 +358,7 @@ sudo nano /etc/ssh/banner
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
```
|
```
|
||||||
|
|
||||||
Добавь в `/etc/ssh/sshd_config.d/99-hardening.conf`:
|
Добавь в `/etc/ssh/sshd_config.d/00-hardening.conf`:
|
||||||
|
|
||||||
```
|
```
|
||||||
Banner /etc/ssh/banner
|
Banner /etc/ssh/banner
|
||||||
@@ -461,59 +463,11 @@ sudo nano /etc/fail2ban/jail.local
|
|||||||
|
|
||||||
```ini
|
```ini
|
||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
# Бан на 1 час
|
|
||||||
bantime = 3600
|
bantime = 3600
|
||||||
# За 10 минут
|
|
||||||
findtime = 600
|
findtime = 600
|
||||||
# После 3 неудачных попыток
|
|
||||||
maxretry = 3
|
maxretry = 3
|
||||||
# Не банить свои IP
|
|
||||||
ignoreip = 127.0.0.1/8 ::1
|
ignoreip = 127.0.0.1/8 ::1
|
||||||
|
|
||||||
[sshd]
|
|
||||||
enabled = true
|
|
||||||
port = 2222
|
|
||||||
filter = sshd
|
|
||||||
logpath = /var/log/auth.log
|
|
||||||
maxretry = 3
|
|
||||||
bantime = 3600
|
|
||||||
```
|
|
||||||
|
|
||||||
Замени `2222` на свой SSH порт.
|
|
||||||
|
|
||||||
**Особенность Ubuntu 24.04:** `systemd-journald` по умолчанию не пишет в `/var/log/auth.log`. Если файл отсутствует или пустой:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ls -la /var/log/auth.log
|
|
||||||
```
|
|
||||||
|
|
||||||
Включи запись в файл:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo nano /etc/rsyslog.d/50-default.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
Убедись что строка не закомментирована:
|
|
||||||
|
|
||||||
```
|
|
||||||
auth,authpriv.* /var/log/auth.log
|
|
||||||
```
|
|
||||||
|
|
||||||
Перезапусти rsyslog:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo systemctl restart rsyslog
|
|
||||||
```
|
|
||||||
|
|
||||||
Или используй journald backend в fail2ban - он умеет читать логи напрямую из journald без файлов:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo nano /etc/fail2ban/jail.local
|
|
||||||
```
|
|
||||||
|
|
||||||
Добавь в секцию `[sshd]`:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[sshd]
|
[sshd]
|
||||||
enabled = true
|
enabled = true
|
||||||
port = 2222
|
port = 2222
|
||||||
@@ -523,7 +477,9 @@ maxretry = 3
|
|||||||
bantime = 3600
|
bantime = 3600
|
||||||
```
|
```
|
||||||
|
|
||||||
При `backend = systemd` параметр `logpath` не нужен - fail2ban читает journald напрямую.
|
Замени `2222` на свой SSH порт.
|
||||||
|
|
||||||
|
`backend = systemd` — обязательно для Ubuntu 24.04. На этом дистрибутиве journald является основным хранилищем логов, файл `/var/log/auth.log` может отсутствовать или не заполняться. При `backend = systemd` параметр `logpath` не нужен — fail2ban читает journald напрямую.
|
||||||
|
|
||||||
Запусти:
|
Запусти:
|
||||||
|
|
||||||
@@ -1065,8 +1021,9 @@ sudo ufw status verbose
|
|||||||
# Статус fail2ban
|
# Статус fail2ban
|
||||||
sudo fail2ban-client status sshd
|
sudo fail2ban-client status sshd
|
||||||
|
|
||||||
# Состояние диска
|
# Определить имя диска и проверить его состояние (только физический сервер)
|
||||||
sudo smartctl -H /dev/sda
|
lsblk -d -o NAME,TYPE | grep disk
|
||||||
|
sudo smartctl -H /dev/ИМЯ_ДИСКА
|
||||||
|
|
||||||
# Swap
|
# Swap
|
||||||
free -h
|
free -h
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ sudo systemctl restart docker
|
|||||||
Проверь:
|
Проверь:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker info | grep -E "Storage Driver|Logging Driver|live-restore"
|
docker info | grep -E "Storage Driver|Logging Driver|Live Restore"
|
||||||
```
|
```
|
||||||
|
|
||||||
## sysctl для Docker-хоста
|
## sysctl для Docker-хоста
|
||||||
@@ -768,7 +768,7 @@ sudo truncate -s 0 /var/lib/docker/containers/CONTAINER_ID/CONTAINER_ID-json.log
|
|||||||
### Финальная проверка
|
### Финальная проверка
|
||||||
```bash
|
```bash
|
||||||
sudo systemctl status docker
|
sudo systemctl status docker
|
||||||
docker info | grep -E "Storage Driver|Logging Driver|live-restore"
|
docker info | grep -E "Storage Driver|Logging Driver|Live Restore"
|
||||||
docker run --rm alpine nslookup google.com
|
docker run --rm alpine nslookup google.com
|
||||||
ss -tulnp | grep docker
|
ss -tulnp | grep docker
|
||||||
docker system df
|
docker system df
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
{{ $coffeeOn := site.Params.buymeacoffee.globalWidget | default false }}
|
||||||
|
{{ $coffeePos := lower (site.Params.buymeacoffee.globalWidgetPosition | default "right") }}
|
||||||
|
{{ $coffeeOnRight := and $coffeeOn (eq $coffeePos "right") }}
|
||||||
|
{{ $scrollTopOn := site.Params.footer.showScrollToTop | default true }}
|
||||||
|
|
||||||
|
{{ $side := "right" }}
|
||||||
|
{{ $bottomPx := 24 }}
|
||||||
|
{{ if $coffeeOnRight }}
|
||||||
|
{{ $side = "left" }}
|
||||||
|
{{ else if $scrollTopOn }}
|
||||||
|
{{ $bottomPx = 90 }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<button id="survey-trigger" type="button" aria-label="Пройти опрос"
|
||||||
|
style="{{ $side }}: 20px; bottom: {{ $bottomPx }}px;">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" aria-hidden="true"><path fill="currentColor" d="M152.1 38.2c9.9 8.9 10.7 24 1.8 33.9l-72 80c-4.4 4.9-10.6 7.8-17.2 7.9s-12.9-2.4-17.6-7L7 113C-2.3 103.6-2.3 88.4 7 79s24.6-9.4 33.9 0l22.1 22.1 55.1-61.2c8.9-9.9 24-10.7 33.9-1.8zm0 160c9.9 8.9 10.7 24 1.8 33.9l-72 80c-4.4 4.9-10.6 7.8-17.2 7.9s-12.9-2.4-17.6-7L7 273c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l22.1 22.1 55.1-61.2c8.9-9.9 24-10.7 33.9-1.8zM224 96c0-17.7 14.3-32 32-32H480c17.7 0 32 14.3 32 32s-14.3 32-32 32H256c-17.7 0-32-14.3-32-32zm0 160c0-17.7 14.3-32 32-32H480c17.7 0 32 14.3 32 32s-14.3 32-32 32H256c-17.7 0-32-14.3-32-32zM160 416c0-17.7 14.3-32 32-32H480c17.7 0 32 14.3 32 32s-14.3 32-32 32H192c-17.7 0-32-14.3-32-32zM48 368a48 48 0 1 1 0 96 48 48 0 1 1 0-96z"/></svg>
|
||||||
|
<span>Опрос</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<script src="https://forms.yandex.ru/_static/embed.js"></script>
|
||||||
|
|
||||||
|
<div id="survey-modal" class="survey-modal" hidden>
|
||||||
|
<div class="survey-modal__overlay" data-survey-close></div>
|
||||||
|
<div class="survey-modal__box">
|
||||||
|
<button class="survey-modal__close" data-survey-close aria-label="Закрыть">×</button>
|
||||||
|
<iframe
|
||||||
|
data-src="https://forms.yandex.ru/cloud/6a6de0cc90290299827b1dca?iframe=1"
|
||||||
|
name="ya-form-6a6de0cc90290299827b1dca"
|
||||||
|
frameborder="0"
|
||||||
|
width="100%"
|
||||||
|
class="survey-modal__iframe"></iframe>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
var article = document.querySelector('.article-content');
|
||||||
|
if (!article) return;
|
||||||
|
|
||||||
|
var DISMISS_KEY = 'survey-dismissed-until';
|
||||||
|
var DISMISS_DAYS = 14;
|
||||||
|
var SCROLL_THRESHOLD = 0.55;
|
||||||
|
|
||||||
|
var trigger = document.getElementById('survey-trigger');
|
||||||
|
var modal = document.getElementById('survey-modal');
|
||||||
|
var iframe = modal ? modal.querySelector('iframe') : null;
|
||||||
|
if (!trigger || !modal) return;
|
||||||
|
|
||||||
|
if (Date.now() < Number(localStorage.getItem(DISMISS_KEY) || 0)) return;
|
||||||
|
|
||||||
|
function onScroll() {
|
||||||
|
var rect = article.getBoundingClientRect();
|
||||||
|
if (rect.height > 0 && (window.innerHeight - rect.top) / rect.height >= SCROLL_THRESHOLD) {
|
||||||
|
trigger.classList.add('is-visible');
|
||||||
|
window.removeEventListener('scroll', onScroll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.addEventListener('scroll', onScroll, { passive: true });
|
||||||
|
onScroll();
|
||||||
|
|
||||||
|
trigger.addEventListener('click', function () {
|
||||||
|
if (iframe && !iframe.src) { iframe.src = iframe.dataset.src; }
|
||||||
|
modal.hidden = false;
|
||||||
|
});
|
||||||
|
modal.querySelectorAll('[data-survey-close]').forEach(function (el) {
|
||||||
|
el.addEventListener('click', function () {
|
||||||
|
modal.hidden = true;
|
||||||
|
localStorage.setItem(DISMISS_KEY, Date.now() + DISMISS_DAYS * 86400000);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
@@ -6,12 +6,82 @@
|
|||||||
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
|
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
|
||||||
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)
|
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)
|
||||||
})(window, document,'script','https://mc.yandex.ru/metrika/tag.js?id=106995329', 'ym');
|
})(window, document,'script','https://mc.yandex.ru/metrika/tag.js?id=106995329', 'ym');
|
||||||
|
|
||||||
ym(106995329, 'init', {ssr:true, webvisor:true, clickmap:true, ecommerce:"dataLayer", referrer: document.referrer, url: location.href, accurateTrackBounce:true, trackLinks:true});
|
ym(106995329, 'init', {ssr:true, webvisor:true, clickmap:true, ecommerce:"dataLayer", referrer: document.referrer, url: location.href, accurateTrackBounce:true, trackLinks:true});
|
||||||
</script>
|
</script>
|
||||||
<noscript><div><img src="https://mc.yandex.ru/watch/106995329" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
|
<noscript><div><img src="https://mc.yandex.ru/watch/106995329" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
|
||||||
<!-- /Yandex.Metrika counter -->
|
<!-- /Yandex.Metrika counter -->
|
||||||
|
|
||||||
<!-- Dzen.Metrika counter -->
|
<!-- Dzen.Metrika counter -->
|
||||||
<meta name="zen-verification" content="GDc1yxlsRy03jcI1t8NJ8OTleUE3f4I4PEmfOBjz4KBCezoDX1WWctO3l8Z2HGEx" />
|
<meta name="zen-verification" content="GDc1yxlsRy03jcI1t8NJ8OTleUE3f4I4PEmfOBjz4KBCezoDX1WWctO3l8Z2HGEx" />
|
||||||
<!-- /Dzen.Metrika counter -->
|
<!-- /Dzen.Metrika counter -->
|
||||||
|
<!-- Survey widget: floating trigger + modal styles -->
|
||||||
|
<style>
|
||||||
|
#survey-trigger {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 40;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 14px 22px;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: none;
|
||||||
|
background: #FF5A36;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(10px) scale(0.9);
|
||||||
|
pointer-events: none;
|
||||||
|
transition: opacity .25s ease, transform .25s ease, background .2s ease;
|
||||||
|
box-shadow: 0 4px 14px rgba(255,90,54,.45);
|
||||||
|
}
|
||||||
|
#survey-trigger:hover { background: #E8481F; }
|
||||||
|
#survey-trigger.is-visible { opacity: 1; transform: translateY(0) scale(1); pointer-events: auto; }
|
||||||
|
#survey-trigger svg { width: 20px; height: 20px; flex-shrink: 0; }
|
||||||
|
.survey-modal {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 10000;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
.survey-modal[hidden] { display: none; }
|
||||||
|
.survey-modal__overlay { position: absolute; inset: 0; background: rgba(0,0,0,.5); }
|
||||||
|
.survey-modal__box {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 680px;
|
||||||
|
max-height: calc(100vh - 32px);
|
||||||
|
max-height: calc(100dvh - 32px);
|
||||||
|
overflow-y: auto;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 44px 8px 8px;
|
||||||
|
}
|
||||||
|
.survey-modal__iframe {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 420px;
|
||||||
|
border: 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.survey-modal__close {
|
||||||
|
position: absolute;
|
||||||
|
top: 8px;
|
||||||
|
right: 8px;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: none;
|
||||||
|
background: #f2f2f2;
|
||||||
|
border-radius: 50%;
|
||||||
|
font-size: 20px;
|
||||||
|
line-height: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.survey-modal__close:hover { background: #e5e5e5; }
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user