Forwarded from localhost
Please open Telegram to view this post
VIEW IN TELEGRAM
2❤8😁7
Одна из старых проблем linux- приложение либо работает от обычного пользователя, либо получает полный root. Но на практике многим сервисам нужен всего один привилегированный доступ. Например:
• открыть порт ниже 1024;
• работать с raw-сокетами;
• менять сетевые настройки;
• выполнять отдельные системные операции.
Давать ради этого полный root - не лучшая идея. Для таких случаев в Linux существуют capabilities. Они разбивают привилегии суперпользователя на отдельные возможности, которые можно выдавать выборочно. К примеру, веб-серверу нужен только доступ к 80 порту. Без root обычный пользователь не сможет открыть этот порт:
python3 -m http.server 80
# Получим ошибку:
Permission denied```
Но можно выдать только capability для привязки к привилегированным портам:
setcap cap_net_bind_service=+ep /usr/bin/python3
Проверяем:
getcap /usr/bin/python3
Результат:
/usr/bin/python3 cap_net_bind_service=ep
Теперь процесс сможет слушать порт 80 без запуска от root. Еще несколько популярных capabilities:
•
CAP_NET_BIND_SERVICE - порты ниже 1024•
CAP_NET_RAW - raw sockets, ping и подобные инструменты•
CAP_SYS_TIME - изменение системного времени•
CAP_NET_ADMIN - управление сетью•
CAP_SYS_ADMIN - очень широкие административные возможности (почти mini-root)Посмотреть capabilities процесса:
cat /proc/<PID>/status | grep Cap
Или использовать:
capsh --print
Удалить capability:
setcap -r /usr/bin/python3
Очень полезны capabilities и в systemd. Например, сервис работает от непривилегированного пользователя:
[Service]
User=nginx
AmbientCapabilities=CAP_NET_BIND_SERVICE
В итоге процесс не получает root, но может слушать 80 и 443 порты. Это гораздо безопаснее, чем запускать весь сервис от суперпользователя. Но не все capabilities одинаково безопасны. Например:
CAP_SYS_ADMIN настолько мощная, что ее часто называют новым root. Поэтому принцип тот же, что и с правами пользователей: выдаем минимум необходимого.Если приложению нужен только доступ к порту 80 - выдаем только
CAP_NET_BIND_SERVICE. Не нужно на всякий случай раздавать весь набор возможностей.#linux #security #capabilities
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤1
Классическая ситуация при миграции сервиса: DNS-запись уже поменяли. На авторитативном DNS новый IP виден. А часть пользователей все равно попадает на старый сервер.
Первое желание - это сказать: "DNS не обновился." Но чаще всего DNS как раз работает правильно. Просто сработал TTL. TTL - это Time To Live, время жизни DNS-записи в кэше. Когда резолвер получил ответ, он имеет право хранить его указанное количество секунд и не спрашивать авторитативный DNS заново. Например:
app.networkadmin.ru. 3600 IN A 203.0.113.10
3600 означает, что запись можно кэшировать 3600 секунд, то есть 1 час. Если вы поменяли IP через 5 минут после того, как чей-то DNS-резолвер закэшировал старый ответ, он может продолжать отдавать старый IP до истечения TTL. И это нормально.
• recursive DNS провайдера
• корпоративный DNS
• DNS-кэш на роутере
• локальный кэш ОС
• браузер
• приложение с собственным DNS-кэшем
• контейнер или runtime
• CDN / reverse proxy
Поэтому один пользователь уже видит новый IP, а другой - старый.
dig app.networkadmin.ru
Спросить конкретный публичный DNS:
dig @8.8.8.8 app.networkadmin.ru
dig @1.1.1.1 app.networkadmin.ru
Спросить авторитативный DNS напрямую:
dig NS networkadmin.ru
dig @ns1.networkadmin.ru app.networkadmin.ru
Во время диагностики важно смотреть не только IP, но и оставшийся TTL:
app.networkadmin.ru. 1842 IN A 203.0.113.10
Если TTL уменьшается - это кэшированный ответ. Если на авторитативном DNS уже новый IP, а у клиента старый - значит где-то по пути еще живет старый кэш.
• Заранее уменьшить TTL, например до 60–300 секунд.
• Подождать старый TTL, чтобы старые кэши успели обновиться.
• Поменять DNS-запись.
• Проверить ответы с разных резолверов.
• Не выключать старый сервер сразу.
Например, если сейчас TTL был 24 часа, нельзя просто поставить TTL 60 и через минуту ждать мгновенного переключения. Сначала нужно дождаться, пока старое значение TTL доживет в кэшах.
• Сегодня в 12:00 TTL был 86400
• Сегодня в 12:05 поставили TTL 60
• Сегодня в 12:10 поменяли IP
А пользователи все еще могут ходить на старый IP до следующего дня, потому что часть резолверов закэшировала запись еще с TTL 86400.
#dns #ttl #network
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
В linux давно уже привычнее смотреть сетевые настройки через
ip, а не через старый ifconfig. Обычно для просмотра адресов используют:
ip a
Команда рабочая, подробная, показывает все. Но иногда этого "все" слишком много. Нужно быстро увидеть:
• интерфейсы
• их состояние
• IPv4/IPv6 адреса
• без лишних строк и простыни вывода
Для этого у ip есть очень удобный ключ:
ip -br a
-br означает brief, то есть краткий вывод.
ip -br a
lo UNKNOWN 127.0.0.1/8 ::1/128
eth0 UP 172.18.107.235/20 fe80::215:5dff:fe0d:7101/64
eth1 UP 192.168.101.2/24 fe80::215:5dff:fe0d:7105/64
docker0 DOWN 172.17.0.1/16
Сразу видно, какой интерфейс поднят, какой адрес назначен и где есть IPv6.
ip -br -4 a
lo UNKNOWN 127.0.0.1/8
eth0 UP 172.18.107.235/20
eth1 UP 192.168.101.2/24
docker0 DOWN 172.17.0.1/16
ip -br -6 a
Это реально удобнее, когда на сервере много интерфейсов: физические NIC, VLAN, bridge, docker-сети, loopback. Не нужно глазами вылавливать IP среди десятков строк. Краткий режим работает не только с адресами.
ip -br link
или короче:
ip -br l
ip -br neigh
или:
ip -br n
ip r
А если нужно понять, куда ядро отправит пакет до конкретного адреса:
ip route get 8.8.8.8
Это часто полезнее, чем просто смотреть всю таблицу маршрутизации.
ip -br a
ip -br -4 a
ip -br -6 a
ip -br l
ip -br n
ip r
ip route get 8.8.8.8
#linux #network
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21
Иногда windows на современном железе оказывается установленной в режиме Legacy BIOS / CSM. Работает и ладно. Но есть нюанс: для нормальной UEFI-загрузки нужен диск с таблицей разделов GPT, а не старый MBR. Почему вообще стоит переходить на UEFI + GPT:
• поддержка дисков больше 2 ТБ;
• больше 4 основных разделов без костылей;
• современный механизм загрузки;
• поддержка Secure Boot;
• меньше зависимости от режима совместимости CSM.
Secure Boot особенно важен: он помогает защититься от подмены загрузчика и запуска вредоносного кода до старта ОС. Если Windows уже установлена в legacy-режиме, не всегда нужно переустанавливать систему. Начиная с Windows 10 1703, есть встроенная утилита:
mbr2gpt
Она умеет конвертировать системный диск из MBR в GPT без удаления данных. Сначала проверяем, в каком режиме загружена Windows:
$env:firmware_type
Если видим: Legacy, значит система загружена в режиме совместимости.
Get-Disk | Get-Partition
Важно: на системном MBR-диске обычно должно быть не больше 3 первичных разделов, потому что mbr2gpt нужно место для создания EFI System Partition.
mbr2gpt /validate /allowFullOS
mbr2gpt /convert /allowFullOS
После этого утилита:
• проверит структуру диска
• создаст EFI-раздел
• сконвертирует MBR в GPT
• добавит UEFI-загрузчик Windows
• обновит загрузочные данные
Дальше нужно перезагрузить компьютер или сервер и зайти в настройки прошивки. Там меняем режим загрузки: Legacy / CSM -> UEFI
Если есть опция boot order, выбираем Windows Boot Manager для нужного диска. После успешной загрузки можно снова проверить режим:
$env:firmware_type
Теперь должно быть: UEFI
#windows #uefi #gpt
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤5👌2
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6😁5
Обычно сервис в linux запускается заранее и постоянно висит в памяти:
systemctl start myapp
Даже если к нему никто не обращается, процесс уже работает, занимает ресурсы и ждет подключения. Но в systemd есть другой подход - socket activation. Идея простая:
• systemd заранее открывает socket или порт;
• сам сервис пока не запущен;
• приходит первый запрос;
• systemd стартует сервис;
• сервис получает уже открытое соединение или socket.
То есть приложение запускается не на всякий случай, а только когда к нему реально обратились. Классический пример - ssh.socket, cups.socket, docker.socket и разные локальные демоны.
Посмотреть активные сокеты:
systemctl list-sockets
Статус конкретного socket-unit:
systemctl status myapp.socket
/etc/systemd/system/myapp.socket:
[Unit]
Description=MyApp socket
[Socket]
ListenStream=8080
[Install]
WantedBy=sockets.target
И сервис /etc/systemd/system/myapp.service:
[Unit]
Description=MyApp service
[Service]
ExecStart=/usr/local/bin/myapp
Включаем именно сокет, а не service:
systemctl daemon-reload
systemctl enable --now myapp.socket
Теперь порт 8080 уже слушается, но сам myapp.service может быть не запущен. Проверяем:
ss -lntp | grep 8080
systemctl status myapp.service
Как только придет подключение на порт 8080, systemd запустит myapp.service.
• экономия ресурсов;
• ленивый запуск редко используемых сервисов;
• ускорение boot-процесса;
• возможность принимать соединения до старта приложения;
• меньше ручной логики вокруг кто должен стартовать первым;
• удобная модель для локальных демонов и admin-инструментов.
Особенно удобно, когда сервис нужен редко, но должен быть доступен сразу при обращении.
Socket activation работает не только с TCP-портами. Можно слушать Unix socket:
[Socket]
ListenStream=/run/myapp.sock
Это часто используют для локального взаимодействия между процессами.
#systemd #socketactivation
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤1
В админских скриптах не все ошибки означают, что все окончательно сломалось. Иногда команда падает из-за временной проблемы:
• сеть моргнула;
• API вернул timeout;
• DNS не ответил с первого раза;
• файл еще не появился;
• сервис еще не успел подняться;
• удаленный хост временно недоступен.
В таких случаях полезна retry-логика - аккуратный повтор операции несколько раз перед тем, как считать задачу проваленной.
curl -fsS https://api.networkadmin.ru/deploy
Если запрос один раз упал - весь скрипт завершился.
for i in {1..5}; do
if curl -fsS https://api.networkadmin.ru/deploy; then
echo "success"
break
fi
echo "attempt $i failed, retrying..."
sleep 5
done
Но у такого варианта есть проблема: после всех неудачных попыток скрипт может продолжить работу, если явно не обработать итог.
retry() {
local max_attempts="$1"
local delay="$2"
shift 2
local attempt=1
until "$@"; do
if (( attempt >= max_attempts )); then
echo "command failed after $attempt attempts: $*" >&2
return 1
fi
echo "attempt $attempt failed, retrying in ${delay}s..." >&2
sleep "$delay"
((attempt++))
done
}
Теперь можно использовать так:
retry 5 3 curl -fsS https://api.networkadmin.ru/health
Или дождаться доступности сервиса:
retry 10 2 nc -z 127.0.0.1 5432
5 или 10 - количество попыток
3 или 2 - пауза между попытками
дальше идет команда, которую нужно повторять
retry_backoff() {
local max_attempts="$1"
local delay="$2"
shift 2
local attempt=1
until "$@"; do
if (( attempt >= max_attempts )); then
echo "command failed after $attempt attempts: $*" >&2
return 1
fi
echo "attempt $attempt failed, retrying in ${delay}s..." >&2
sleep "$delay"
delay=$((delay * 2))
((attempt++))
done
}
Пример:
retry_backoff 5 2 curl -fsS https://api.networkadmin.ru/status
Паузы будут примерно такими: 2s -> 4s -> 8s -> 16s
Это лучше, чем агрессивно долбить нестабильный сервис каждые 100 мс.
#bash #automation
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤1
rsync - одна из тех утилит, которые годами живут в админских скриптах и не теряют актуальности. Ее любят за простую идею: сравнить источник и приемник, а потом скопировать только то, что реально изменилось. Особенно хорошо rsync показывает себя на каталогах с большим количеством файлов. Если нужно синхронизировать два хранилища с сотнями тысяч или миллионами объектов, обычное копирование быстро превращается в боль. У rsync есть минусы. Главный - он не становится магически многопоточным. Но для задач, где нужно копировать файлы как есть, без упаковки, дедупликации и сложных backup-форматов, это все еще очень удобный инструмент. Ниже несколько ключей, которые полезно помнить.
rsync -av --delete source/ dest/
Но для бэкапов часто важно не просто удалить старые или измененные файлы, а сохранить их отдельно. Для этого есть связка:
--backup
--backup-dir=/path/to/old-files
Пример:
rsync -av --delete --backup \
--backup-dir="/mnt/data/backup/bases_increment/$(date +%F)/" \
back_user@10.20.5.22:/var/lib/pgpro/backup/ \
/mnt/data/backup/bases/ \
>> "/var/log/rsync/1Csrv-$(date +%F).log"
• новые файлы попадут в основной каталог бэкапа;
• файлы, которые должны быть удалены или заменены, будут перемещены в backup-dir;
• изменения за конкретный день окажутся в отдельной папке;
• глубину хранения можно потом регулировать через find.
Это удобно, если нужно видеть, что именно изменилось между запусками. Например, если на сайте кто-то заменил несколько файлов, при очередном бэкапе старые версии можно будет найти в отдельном каталоге.
rsync -av --progress source/ dest/
В логе будет видно размер, скорость и время передачи. Это удобно для крупных файлов: дампов баз, архивов, образов. Но если файлов очень много и они мелкие,
--progress может сильно засорить вывод. В таких случаях лучше использовать более спокойный режим:
rsync -av --info=progress2 source/ dest/
или вообще убрать прогресс из cron-задачи.
Например, кто-то удалил часть файлов в
/var/www, а мы хотим вернуть недостающее из бэкапа:
rsync -av --ignore-existing \
back_user@10.30.7.5:/mnt/backup/www/ \
/var/www/
• отсутствующие файлы будут скопированы;
• существующие файлы не будут перезаписаны;
• даже если в бэкапе версия новее, rsync ее не тронет.
Это хороший вариант для аккуратного "докинуть недостающее".
rsync -av --update \
back_user@10.30.7.5:/mnt/backup/www/ \
/var/www/
Если файла в приемнике нет - он будет скопирован. Если файл уже есть и он новее, rsync его не перезапишет. Этот ключ полезен, когда данные собираются из разных источников и нужно оставить самые свежие версии файлов.
rsync -av --delete --dry-run source/ dest/
или короче:
rsync -avn --delete source/ dest/
--dry-run показывает, что rsync сделал бы, но ничего реально не меняет. Это спасает от классической ошибки: перепутали источник и приемник - и удалили не там. Перед первой настройкой бэкапа или синхронизации лучше всегда запускать тестовый прогон.
rsync -av /data/source/ /backup/source/
копирует содержимое каталога source. А так:
rsync -av /data/source /backup/
копирует сам каталог source внутрь
/backup. На первый взгляд мелочь, но из-за этого часто получают не ту структуру директорий.#linux #rsync
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Иногда техподдержке нужно быстро понять, что происходит на рабочем месте пользователя. Например:
• пользователь не может нормально описать ошибку;
• окно с сообщением быстро исчезает;
• приложение зависло в нестандартном состоянии;
• нужно увидеть текущий экран без полноценного подключения по RDP/AnyDesk;
• удаленный просмотр экрана в компании не используется или ограничен.
В таких случаях можно сделать простой механизм: по заявке и с согласия пользователя получить скриншот его текущего рабочего стола и сохранить PNG-файл в сетевую папку. Один из вариантов - PowerShell-скрипт, который делает снимок экрана в интерактивной сессии пользователя, и удаленный запуск через PsExec. Пример запуска:
.\PsExec.exe -s -i 1 \\pk-ww01 powershell.exe `
-ExecutionPolicy Bypass `
-WindowStyle Hidden `
-File "\\fs01\scripts\PS-Capture-Local-Screen.ps1"
\\pk-ww01 - удаленная рабочая станция-s - запуск от имени Local System-i 1 - запуск в интерактивной сессии пользователяpowershell.exe - выполнение PowerShell-скрипта\\fs01\scripts\... - путь к скрипту на файловом сервереСам скрипт делает снимок рабочего стола и сохраняет файл, например, в общую сетевую папку:
\\fs01\support\screenshots\. И дальше сотрудник техподдержки может открыть PNG-файл и посмотреть, что было на экране в момент обращения.#powershell #psexec
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Когда на linux работает NAT или stateful firewall, почти всегда где-то рядом есть conntrack. Conntrack - это механизм ядра, который отслеживает сетевые соединения. Он нужен, чтобы firewall понимал не только отдельный пакет, но и его состояние:
• это новое соединение;
• это ответ на уже разрешенное соединение;
• это часть существующей сессии;
• это странный или неожиданный пакет.
Именно поэтому в iptables/nftables часто встречается логика:
-m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
или в nftables:
ct state established,related accept
Смысл простой: если соединение уже разрешено, ответы по нему пропускаем автоматически. Без conntrack не было бы привычного NAT, нормального stateful firewall и многих схем с masquerade. Но у conntrack есть цена. Каждое отслеживаемое соединение попадает в таблицу conntrack. Если соединений много, таблица растет. Если таблица переполнена, начинаются неприятности.
• новые подключения отваливаются;
• NAT начинает работать нестабильно;
• часть клиентов не может открыть сайт;
• DNS-запросы теряются;
• в логах появляются сообщения про переполнение conntrack;
• снаружи кажется, что "сеть иногда моргает".
sysctl net.netfilter.nf_conntrack_max
Посмотреть текущее количество записей:
cat /proc/sys/net/netfilter/nf_conntrack_count
Если значение
nf_conntrack_count регулярно подходит к nf_conntrack_max, система близка к проблемам.Еще можно посмотреть события в kernel log:
dmesg | grep -i conntrack
Типичная ошибка:
nf_conntrack: table full, dropping packet. Это уже прямой сигнал: таблица заполнена, новые пакеты начинают отбрасываться.
conntrack -L
Но на нагруженных серверах с этим осторожно: вывод может быть огромным. Для общей статистики лучше:
conntrack -S
Где conntrack часто становится узким местом:
• NAT-шлюзы
• Kubernetes-ноды
• Docker-хосты
• DNS-рекурсоры
• reverse proxy под большой нагрузкой
• серверы с большим количеством коротких соединений
sysctl -w net.netfilter.nf_conntrack_max=262144
Для постоянной настройки:
echo "net.netfilter.nf_conntrack_max=262144" > /etc/sysctl.d/99-conntrack.conf
sysctl --system
Но просто поднять лимит не всегда решение. Нужно понимать, почему таблица растет: слишком много коротких соединений, DDoS или сканирование, долгие таймауты или что-то другое. Иногда помогает настройка timeout’ов. Например, для TCP established:
sysctl net.netfilter.nf_conntrack_tcp_timeout_established
Для UDP:
sysctl net.netfilter.nf_conntrack_udp_timeout
sysctl net.netfilter.nf_conntrack_udp_timeout_stream
Но менять таймауты нужно аккуратно. Слишком короткие значения могут ломать нормальные долгоживущие соединения.
#linux #network #conntrack
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1
В windows server есть встроенный механизм объединения дисков - Storage Spaces. По сути, это программное хранилище, которое позволяет собрать несколько физических дисков в пул, а поверх него создать виртуальный диск с нужным типом отказоустойчивости. То есть вместо классического аппаратного RAID-контроллера можно использовать возможности самой windows.
Базовая схема: Physical disks -> Storage Pool -> Virtual Disk -> Volume
В пул добавляются физические диски, а дальше из этого пула создается виртуальный диск.
• Simple. Без отказоустойчивости. Аналог striping. Быстро, но при потере диска теряются данные.
• Mirror. Зеркалирование данных. Похоже на RAID1 или RAID10.
• Parity. Данные + контроль четности. Похоже на RAID5/RAID6 по идее, но не всегда по производительности.
• файловый сервер;
• backup-хранилище;
• сервер с большим количеством локальных дисков;
• недорогая замена аппаратному RAID для не самых критичных задач;
• сценарии, где нужна гибкость, а не максимальная производительность.
Get-PhysicalDisk
Создать storage pool:
New-StoragePool `
-FriendlyName "DataPool" `
-StorageSubsystemFriendlyName "Windows Storage*" `
-PhysicalDisks (Get-PhysicalDisk -CanPool $true)
Создать mirror virtual disk:
New-VirtualDisk `
-StoragePoolFriendlyName "DataPool" `
-FriendlyName "DataMirror" `
-ResiliencySettingName Mirror `
-UseMaximumSize
После этого диск можно инициализировать, создать раздел и отформатировать:
Get-VirtualDisk -FriendlyName "DataMirror" | Get-Disk |
Initialize-Disk -PartitionStyle GPT -PassThru |
New-Partition -UseMaximumSize -DriveLetter D |
Format-Volume -FileSystem NTFS -NewFileSystemLabel "Data"
• не нужен отдельный RAID-контроллер;
• проще переносить диски между совместимыми windows-системами;
• управление через PowerShell;
• можно гибко добавлять диски в пул;
• нет зависимости от конкретной модели RAID-контроллера;
• хорошо подходит для типовых windows-хранилищ.
Но есть нюансы. Storage Spaces - это не "бесплатный аппаратный RAID лучше во всем". У parity-сценариев может быть слабая производительность на записи, особенно на обычных HDD. Для баз данных, виртуализации и высоконагруженных задач нужно тщательно тестировать.
Проверять состояние можно так:
Get-StoragePool
Get-VirtualDisk
Get-PhysicalDisk
Если диск начал сыпаться, это нужно увидеть не тогда, когда уже умер второй.
#windowsserver #storagespaces
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🫡2❤1👌1
Когда сервис не открывается, то первое желание часто такое: сразу лезть в конфиги приложения, firewall, nginx, systemd и логи. Но иногда полезнее начать с более простого вопроса: а пакеты вообще доходят до сервера? Для этого есть старый добрый
tcpdump. Он позволяет посмотреть сетевой трафик прямо на интерфейсе и быстро понять, видит ли сервер входящие пакеты. Например, пользователь говорит: "Не открывается сайт на 443 порту".
tcpdump -i any port 443
И просим пользователя повторить подключение. Если в выводе появились пакеты - до сервера что-то доходит. Если тишина - проблема может быть раньше:
• firewall перед сервером;
• security group;
• маршрутизация;
• NAT;
• балансировщик;
• неправильный IP;
• провайдерская фильтрация;
• подключение вообще идет не туда.
tcpdump -i any 'tcp port 443 and tcp[tcpflags] & tcp-syn != 0'
SYN - это начало TCP-подключения. Если SYN приходит, значит клиент хотя бы пытается установить соединение с сервером. Можно сразу фильтровать по IP клиента:
tcpdump -i any host 203.0.113.10 and port 443
Так удобнее, если на сервере много трафика и общий вывод превращается в кашу.
Если нужно проверить SSH:
tcpdump -i any port 22
Если HTTP:
tcpdump -i any port 80
Если DNS:
tcpdump -i any port 53
Для UDP-сервисов тоже работает:
tcpdump -i any udp port 1194
-n -Не резолвить имена. Вывод будет быстрее и чище.-nn - Не резолвить ни имена, ни порты. Вместо https будет 443.-v - Более подробный вывод.-c 20 - Поймать 20 пакетов и завершиться.
tcpdump -i any -nn -c 20 host 203.0.113.10 and port 443
203.0.113.10.53044 > 10.0.0.5.443: Flags [S]
А следом должен быть ответ сервера:
10.0.0.5.443 > 203.0.113.10.53044: Flags [S.]
Если входящий SYN есть, но ответа нет - нужно смотреть локальный firewall, сервис, listen-порт или routing обратно. Проверяем, слушает ли порт:
ss -lntp | grep ':443'
Проверяем firewall:
iptables -S
nft list ruleset
Если SYN приходит и SYN-ACK уходит, но клиент все равно не подключается - возможно, проблема на обратном пути.
ip a
tcpdump -i eth0 -nn port 443
any удобен для быстрой диагностики, но конкретный интерфейс помогает понять, через какую сетевую карту реально идет трафик.
tcpdump -i any -nn host 203.0.113.10 -w capture.pcap
Это удобно, если проблему нужно передать сетевикам или разобрать позже.
#linux #tcpdump #network
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤2🔥1
Одна из классических проблем в windows-инфраструктуре: на всех рабочих станциях один и тот же пароль локального администратора. Выглядит удобно. Админу легко подключиться к любой машине. Пароль можно держать для экстренных случаев. Техподдержка знает, что делать, если доменная авторизация не работает. Но с точки зрения безопасности это очень плохая идея. Если пароль локального администратора утек с одной машины, атакующий фактически получает доступ ко всем хостам, где этот пароль такой же. Именно для решения этой проблемы существует Windows LAPS.
Идея простая: у каждой машины должен быть свой уникальный пароль локального администратора, который регулярно меняется автоматически. Не один общий пароль на весь офис. Не excel-файл с паролями. А отдельный пароль для каждого компьютера.
• на компьютере есть локальная admin-учетка;
• LAPS генерирует для нее уникальный пароль;
• пароль сохраняется в Active Directory или Entra ID;
• доступ к паролю получают только разрешенные админы;
• пароль автоматически меняется по политике;
• после использования пароль можно сбросить повторно.
Раньше часто использовали microsoft LAPS как отдельный компонент. Сейчас есть windows LAPS, встроенный в современные версии windows. Он поддерживает хранение паролей в active directory и microsoft entra ID.
• Включаем поддержку Windows LAPS.
• Настраиваем права в Active Directory.
• Создаем Group Policy.
• Указываем, какую локальную учетку админа обслуживать.
• Задаем параметры пароля и срок жизни.
• Проверяем, что пароль появился у объекта компьютера.
Get-LapsADPassword -Identity "PC-001" -AsPlainText
Так можно получить пароль локального администратора для конкретной машины, если у учетной записи есть права.
Посмотреть параметры LAPS на клиенте:
Get-LapsDiagnostics
Принудительно обновить пароль:
Reset-LapsPassword
• имя локальной admin-учетки;
• длину пароля;
• сложность пароля;
• срок действия пароля;
• место хранения пароля;
• права на чтение пароля;
• действия после использования пароля.
Например, можно сделать так, чтобы пароль менялся каждые 30 дней. Или сбрасывался сразу после того, как админ его использовал.
Главная польза LAPS: компрометация одной машины не дает автоматический доступ ко всем остальным. Даже если пароль локального администратора слили с одного ПК, на другом компьютере он будет другим. Это резко снижает риск распространения атаки внутри сети.
#windows #security
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤2
В systemd часто нужно чуть-чуть изменить стандартный unit, который приехал из пакета. Например:
• добавить автоматический рестарт;
• изменить переменные окружения;
• переопределить ExecStart;
• добавить лимиты;
• поменять рабочий каталог;
• настроить зависимости.
Плохая идея - править vendor-unit напрямую где-нибудь в:
/lib/systemd/system/
или:
/usr/lib/systemd/system/
После обновления пакета такие изменения могут потеряться или конфликтовать с новой версией юнита.Правильнее использовать override. Покажу на примере nginx.service.
systemctl cat nginx.service
Это очень удобная команда. Она показывает не только содержимое unit-файла, но и путь, откуда он загружен. Если для сервиса уже есть override-файлы, они тоже будут показаны в этом же выводе.
systemctl edit nginx.service
[Service]
Restart=always
RestartSec=5s
/etc/systemd/system/nginx.service.d/override.conf
systemctl cat nginx.service
Теперь в выводе будет видно и исходный unit, и наш override.
systemctl daemon-reload
systemctl restart nginx.service
И проверить:
systemctl status nginx.service
Важный нюанс: не все параметры переопределяются одинаково. Если вы добавляете новый параметр, обычно достаточно просто указать его. Например:
[Service]
Restart=always
RestartSec=5s
Но если нужно переопределить параметры, которые могут иметь несколько значений, их часто нужно сначала очистить.
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
А вы хотите заменить команду запуска, нужно сделать так:
[Service]
ExecStart=
ExecStart=/usr/sbin/nginx -g 'daemon off; master_process off;'
Первая строка очищает старое значение. Вторая задает новое. Если просто добавить новый ExecStart, systemd может выдать ошибку или оставить некорректную конфигурацию. То же часто касается параметров семейства:
ExecStart=
ExecStartPre=
ExecStartPost=
ExecReload=
ExecStop=
systemctl cat nginx.service
И затем:
systemd-analyze verify /etc/systemd/system/nginx.service.d/override.conf
Еще полезная команда:
systemctl revert nginx.service
Она удалит локальные override и вернет unit к vendor-состоянию.
#linux #systemd
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
У Microsoft Sysinternals есть старая, но до сих пор полезная утилита - BgInfo. Она выводит системную информацию прямо поверх обоев рабочего стола. На фоне можно показать:
• имя компьютера
• домен
• пользователя
• IP-адреса
• версию Windows
• uptime
• свободное место на дисках
• AD site
• любые дополнительные поля
Для HelpDesk это удобно: пользователь просто смотрит на рабочий стол и диктует нужные данные. Для админа тоже полезно, особенно когда открыто много RDP-сессий на разные серверы. Сразу видно, где именно ты находишься, и меньше шансов перепутать тестовый сервер с боевым.
BgInfo достаточно гибкий. Кроме стандартных полей, можно добавлять данные через:
• WMI
• registry
• environment variables
• VBS
• PowerShell-скрипты
bg_config.bgi
\\domain.local\NETLOGON\Bginfo\
Внутри:
Bginfo.exe
bg_config.bgi
reg add HKEY_CURRENT_USER\Software\Sysinternals\BGInfo /v EulaAccepted /t REG_DWORD /d 1 /f
%logonserver%\NETLOGON\Bginfo\Bginfo.exe %logonserver%\NETLOGON\Bginfo\bg_config.bgi /silent /timer:00 /nolicprompt
• заранее принимаем EULA для пользователя
• запускаем BgInfo из NETLOGON
• применяем готовый .bgi шаблон
• скрываем окно запуска
• не показываем license prompt
• сразу обновляем фон без ожидания таймера
После входа пользователя на рабочий стол автоматически наносится нужная системная информация.
Отдельный плюс - возможность стандартизировать внешний вид. Например, на серверах можно крупно выводить:
SERVER: SRV-APP-01
ENV: PROD
IP: 10.10.20.15
А на рабочих станциях - имя ПК, пользователь, IP и версию ОС.
#windows #bginfo
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14
Многие Bash-скрипты сначала выглядят просто:
./backup.sh /data /backupА потом появляются опции: путь к конфигу, имя окружения, количество попыток, режим работы и т.д. И скрипт быстро превращается в набор странных if, где $1, $2, $3 уже никто нормально не понимает.
SOURCE="$1"
DEST="$2"
MODE="$3"
Работает, пока аргументов мало. Но как только нужно добавить флаги, порядок начинает ломать все. Для нормального разбора коротких опций в bash есть встроенный механизм getopts.
#!/usr/bin/env bash
set -euo pipefail
VERBOSE=0
DRY_RUN=0
CONFIG=""
usage() {
echo "Usage: $0 [-v] [-n] [-c config] source dest"
}
while getopts ":vnc:" opt; do
case "$opt" in
v)
VERBOSE=1
;;
n)
DRY_RUN=1
;;
c)
CONFIG="$OPTARG"
;;
🙂
echo "option -$OPTARG requires an argument" >&2
usage
exit 1
;;
\?)
echo "unknown option: -$OPTARG" >&2
usage
exit 1
;;
esac
done
shift $((OPTIND - 1))
SOURCE="${1:-}"
DEST="${2:-}"
if [[ -z "$SOURCE" || -z "$DEST" ]]; then
usage
exit 1
fi
echo "source: $SOURCE"
echo "dest: $DEST"
echo "config: $CONFIG"
echo "verbose: $VERBOSE"
echo "dry-run: $DRY_RUN"
Теперь скрипт можно запускать так:
./backup.sh -v -n -c /etc/backup.conf /data /backup
или так:
./backup.sh -c /etc/backup.conf -v /data /backup
Порядок флагов уже не так важен.
while getopts ":vnc:" opt; dov - флаг без значенияn - флаг без значенияc: - опция -c требует аргументпервый
: включает более удобную обработку ошибокТо есть
-v и -n просто включают режимы, а -c ожидает значение:
-c /etc/backup.conf
Переменная OPTARG содержит аргумент текущей опции. Например, для:
-c /etc/backup.conf
внутри case будет:
CONFIG="$OPTARG"
После обработки флагов важна команда:
shift $((OPTIND - 1))
Она убирает уже разобранные опции из списка аргументов. После этого в
$1, $2 остаются обычные позиционные аргументы: например source и dest.#bash #scripting
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Иногда приложение вроде бы работает, CPU нормальный, память есть, база живая, но пользователи жалуются: "все медленно". И начинается классика: смотрим логи приложения, nginx, базу, systemd, load average. А причина может быть ниже - на сетевом уровне. Один из важных признаков сетевых проблем - TCP retransmits.
TCP - надежный протокол. Если пакет потерялся по дороге, получатель его не подтвердил, и отправитель через время отправит этот сегмент заново. Это и есть retransmission. Небольшое количество повторных передач в сети бывает всегда. Но если их много - это уже симптом:
• перегруженный канал;
• проблемы на интерфейсе;
• плохой Wi-Fi или VPN;
• перегруженный firewall/NAT;
• проблемы у провайдера.
Снаружи это часто выглядит не как "сеть упала", а как странная деградация: страницы открываются медленно, API иногда отвечает долго, SSH подвисает, загрузка файлов идет рывками и т.д.
Первое, что можно посмотреть на linux:
netstat -s | grep -i retrans
или через ss:
ss -ti
В выводе
ss -ti можно увидеть детали по TCP-соединениям, включая retrans, rtt, cwnd и другие параметры.Для конкретного направления лучше использовать
tcpdump. Например, смотрим трафик между сервером и клиентом:
tcpdump -i any -nn host 203.0.113.10 and port 443
Если нужно сохранить дамп для Wireshark:
tcpdump -i any -nn host 203.0.113.10 and port 443 -w retrans.pcap
В wireshark потом удобно фильтровать:
tcp.analysis.retransmission
Также полезные фильтры:
tcp.analysis.fast_retransmission
tcp.analysis.lost_segment
tcp.analysis.duplicate_ack
Если видите много retransmission, duplicate ACK и lost segment - это уже повод смотреть сеть, а не только приложение.
Быстрая проверка маршрута:
mtr -rw -c 100 203.0.113.10
Но тут важно помнить: mtr показывает потери по ICMP/UDP/TCP-проверкам, а не всегда идеально отражает конкретный TCP-трафик приложения. Зато помогает понять, где примерно начинаются проблемы.
Еще полезно проверить ошибки на сетевом интерфейсе:
ip -s link
или:
ethtool -S eth0
#linux #network
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤2
sshfs позволяет монтировать удаленную файловую систему через обычное SSH-соединение. То есть если у вас есть SSH-доступ к серверу, можно подключить его каталог как локальную директорию. Это не самый быстрый способ: SSHFS работает через FUSE в user space, плюс само SSH-соединение добавляет накладные расходы. Но для некоторых задач это очень удобно. Особенно когда: SSH уже открыт; NFS/SMB поднимать не хочется; нужен быстрый доступ к отдельному каталогу или нужно временно подключить данные
apt install sshfs
ssh-keygen -t ed25519
Копируем его на удаленный сервер:
ssh-copy-id root@10.20.1.6
Можно подключаться и по паролю, но для systemd-автомонтирования это неудобно: пароль придется вводить интерактивно. С ключом все проще и надежнее.
root@10.20.1.6:/etc/letsencrypt
в локальный путь:
/mnt/letsencrypt
Создаем точку монтирования:
mkdir -p /mnt/letsencrypt
Монтируем вручную:
sshfs root@10.20.1.6:/etc/letsencrypt /mnt/letsencrypt
Проверяем:
df -h | grep 10.20.1.6
Размонтировать можно так:
fusermount -u /mnt/letsencrypt
systemctl edit --force --full sshfs-letsencrypt.service
Пример unit-файла:
[Unit]
Description=Mount /etc/letsencrypt over SSHFS
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/bin/sshfs root@10.20.1.6:/etc/letsencrypt /mnt/letsencrypt -o reconnect,ServerAliveInterval=15,ServerAliveCountMax=3
ExecStop=/usr/bin/fusermount -u /mnt/letsencrypt
[Install]
WantedBy=multi-user.target
Перечитываем systemd:
systemctl daemon-reload
Запускаем:
systemctl start sshfs-letsencrypt.service
Добавляем в автозагрузку:
systemctl enable sshfs-letsencrypt.service
Если нужно размонтировать каталог:
systemctl stop sshfs-letsencrypt.service
•
reconnect - Пытаться восстановить подключение при обрыве.•
ServerAliveInterval=15 - Периодически проверять, живо ли SSH-соединение.•
ServerAliveCountMax=3 - После нескольких неудачных проверок считать соединение мертвым.В примере все сделано от root для простоты. Для постоянной схемы лучше использовать отдельного пользователя с минимальными правами. В systemd можно указать:
User=sftp-user
Group=sftp-user
Но тогда важно, чтобы у этого пользователя были права на точку монтирования и SSH-ключи.
#linux #sshfs
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤1
В Windows-скриптах часто делают логирование в обычные текстовые файлы:
C:\Scripts\Logs\script.log
Это рабочий вариант, но не всегда удобный. Логи могут лежать в разных папках, забываться при переносе скрипта, не попадать в централизованный сбор и быстро превращаться в зоопарк форматов. Иногда удобнее писать важные события прямо в Event Viewer.
• события видны в стандартном журнале Windows;
• их можно собирать через WEF, SIEM или агент мониторинга;
• проще фильтровать по источнику, Event ID и уровню;
• не нужно отдельно искать лог-файл скрипта;
• события попадают в привычный механизм аудита и диагностики.
New-EventLog -LogName Application -Source "MyScript"
После этого можно писать события в журнал Application:
Write-EventLog `
-LogName Application `
-Source "MyScript" `
-EntryType Information `
-EventID 1 `
-Message "Запущен PowerShell-скрипт опроса состояния сервера"
В Event Viewer появится событие с источником MyScript.
Тип события можно менять:
-EntryType Information
-EntryType Warning
-EntryType Error
Например, если скрипт завершился с ошибкой:
Write-EventLog `
-LogName Application `
-Source "MyScript" `
-EntryType Error `
-EventID 1001 `
-Message "Скрипт завершился с ошибкой при подключении к серверу"
1 - старт скрипта
2 - успешное завершение
100 - предупреждение
1001 - ошибка подключения
1002 - ошибка доступа
Так потом проще строить фильтры и алерты.
New-EventLog -LogName CustomPSLog -Source "PS1Script"
И писать уже туда:
Write-EventLog `
-LogName CustomPSLog `
-Source "PS1Script" `
-EntryType Information `
-EventID 1 `
-Message "PowerShell script started"
eventcreate /t information /l application /id 1 /d "BAT script started"
Для ошибки:
eventcreate /t error /l application /id 1001 /d "BAT script failed"
Event Viewer удобен не вместо всех логов, а как место для важных событий, которые должны быть видны системе мониторинга и администратору. Если скрипт делает что-то важное, он должен не просто молча выполниться. Он должен оставить понятный след: когда стартовал, чем закончился и где сломался.
#windows #powershell #eventviewer
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7