Собираем Samba NAS в Proxmox LXC. Часть 5: Публичная read-only шара
Создаём публичную read-only Samba-шару Public в Proxmox LXC: гостевой доступ, SMB3, безопасные права и bash-скрипт.
Задача
В предыдущих частях мы сделали:
[share]— основную рабочую шару;[secure]— защищённую шару;- audit для
[secure].
Теперь добавим публичную read-only шару:
1
\\nas\public
Она нужна для файлов, которые можно читать всем:
- инструкции;
- ISO-образы;
- драйверы;
- публичные документы;
- общие материалы;
- файлы для быстрой передачи внутри LAN.
Требования:
- доступ без пароля;
- только чтение;
- отдельный каталог
/srv/samba/public; - безопасные права;
- не перезатирать текущий
smb.conf; - проверить конфиг перед перезапуском.
[public]— это не место для рабочих документов. Всё, что требует контроля доступа, должно лежать в[share]или[secure].
Архитектура
После этой части структура будет такой:
1
2
3
4
/srv/samba
├── public # guest read-only
├── share # user writable
└── secure # user writable + encryption + audit
Важный момент про guest-доступ
Для guest-шары в Samba обычно нужен глобальный параметр:
1
map to guest = Bad User
Он говорит Samba: если пришёл неизвестный пользователь, можно сопоставить его с guest-учёткой.
Но сам guest-доступ должен быть разрешён только в конкретной шаре:
1
2
3
[public]
guest ok = yes
read only = yes
Так мы не делаем весь сервер анонимным, а разрешаем guest только в [public].
Скрипт add-public-smb-share.sh
Скрипт:
- создаёт каталог
/srv/samba/public; - выставляет
755; - добавляет
[public]; - проверяет наличие
map to guest = Bad User; - делает backup;
- проверяет
testparm; - перезапускает Samba.
Создай файл:
1
nano add-public-smb-share.sh
Вставь:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env bash
set -Eeuo pipefail
# ============================================================
# SMB на bash. Часть 5. Public
# Добавление read-only guest-шары [public]
# ============================================================
SHARE_NAME="${SHARE_NAME:-public}"
PUBLIC_DIR="${PUBLIC_DIR:-/srv/samba/public}"
SMB_CONF="${SMB_CONF:-/etc/samba/smb.conf}"
GUEST_USER="${GUEST_USER:-nobody}"
GUEST_GROUP="${GUEST_GROUP:-nogroup}"
require_root() {
if [[ "${EUID}" -ne 0 ]]; then
echo "Ошибка: запусти скрипт от root"
exit 1
fi
}
check_requirements() {
if [[ ! -f "${SMB_CONF}" ]]; then
echo "Ошибка: не найден ${SMB_CONF}"
echo "Сначала выполни часть 2 и создай базовую Samba-конфигурацию."
exit 1
fi
if ! id "${GUEST_USER}" &>/dev/null; then
echo "Ошибка: пользователь ${GUEST_USER} не найден"
exit 1
fi
if ! getent group "${GUEST_GROUP}" >/dev/null; then
echo "Группа ${GUEST_GROUP} не найдена, пробуем использовать nobody"
GUEST_GROUP="nobody"
fi
}
prepare_dir() {
echo "==> Создаём каталог ${PUBLIC_DIR}"
mkdir -p "${PUBLIC_DIR}"
chown "${GUEST_USER}:${GUEST_GROUP}" "${PUBLIC_DIR}"
chmod 0755 "${PUBLIC_DIR}"
}
backup_config() {
local backup="${SMB_CONF}.bak.public.$(date +%F_%H-%M-%S)"
echo "==> Делаем backup ${backup}"
cp "${SMB_CONF}" "${backup}"
}
ensure_global_guest_mapping() {
if grep -qE '^[[:space:]]*map to guest[[:space:]]*=' "${SMB_CONF}"; then
echo "==> map to guest уже настроен"
return
fi
echo "==> Добавляем map to guest = Bad User в [global]"
awk '
BEGIN { in_global = 0; added = 0 }
/^\[global\]/ {
in_global = 1
print
next
}
in_global && /^\[/ && added == 0 {
print " map to guest = Bad User"
added = 1
in_global = 0
}
{ print }
END {
if (in_global && added == 0) {
print " map to guest = Bad User"
}
}
' "${SMB_CONF}" > /tmp/smb.conf.public
mv /tmp/smb.conf.public "${SMB_CONF}"
}
ensure_share_not_exists() {
if grep -qE "^\[${SHARE_NAME}\]" "${SMB_CONF}"; then
echo "Шара [${SHARE_NAME}] уже существует — пропускаем"
exit 0
fi
}
append_share() {
echo "==> Добавляем шару [${SHARE_NAME}]"
cat >> "${SMB_CONF}" <<EOF
[${SHARE_NAME}]
path = ${PUBLIC_DIR}
guest ok = yes
public = yes
read only = yes
writable = no
browseable = yes
force user = ${GUEST_USER}
force group = ${GUEST_GROUP}
EOF
}
validate_config() {
echo "==> Проверяем Samba config"
testparm -s "${SMB_CONF}" >/dev/null
}
restart_samba() {
echo "==> Перезапускаем Samba"
systemctl restart smbd
}
print_summary() {
local host
host="$(hostname -f 2>/dev/null || hostname)"
echo
echo "Готово."
echo "Публичная read-only шара создана:"
echo " //${host}/${SHARE_NAME}"
echo
echo "Каталог:"
echo " ${PUBLIC_DIR}"
echo
echo "Проверка:"
echo " smbclient //SERVER_IP/${SHARE_NAME} -N -m SMB3"
}
main() {
require_root
check_requirements
prepare_dir
backup_config
ensure_global_guest_mapping
ensure_share_not_exists
append_share
validate_config
restart_samba
print_summary
}
main "$@"
Запуск
1
2
chmod +x add-public-smb-share.sh
sudo ./add-public-smb-share.sh
Добавим тестовый файл
1
2
echo "Hello from public Samba share" | sudo tee /srv/samba/public/readme.txt
sudo chmod 0644 /srv/samba/public/readme.txt
Проверка с Linux
Список шар:
1
smbclient -L //SERVER_IP -N -m SMB3
Подключение к public без пароля:
1
smbclient //SERVER_IP/public -N -m SMB3
Внутри:
1
2
3
smb: \> ls
smb: \> get readme.txt
smb: \> put test.txt
Команда put test.txt должна завершиться ошибкой, потому что шара read-only.
Проверка с Windows
Открыть в проводнике:
1
\\SERVER_IP\public
Или подключить как диск:
net use P: \\SERVER_IP\public /user:guest ""
Почему public должна быть read-only
Публичная writable-шара — это почти всегда проблема.
Если разрешить запись без пароля, любой клиент в сети сможет:
- загрузить мусор;
- удалить файлы;
- положить вредоносный файл;
- заполнить диск;
- устроить хаос в каталоге.
Поэтому для публичного доступа лучше использовать принцип:
1
2
read-only по сети
write только локально администратором
Если нужно место для обмена файлами, лучше сделать отдельную authenticated-шару, например [upload], а не превращать [public] в общую корзину.
Возможные ошибки
NT_STATUS_ACCESS_DENIED при подключении без пароля
Проверь:
1
testparm -s | grep -E 'map to guest|guest ok|public'
В конфиге должны быть:
1
2
map to guest = Bad User
guest ok = yes
Видно шару, но нельзя читать файлы
Проверь права:
1
2
ls -ld /srv/samba/public
ls -la /srv/samba/public
Исправить:
1
2
3
sudo chown -R nobody:nogroup /srv/samba/public
sudo chmod 0755 /srv/samba/public
sudo find /srv/samba/public -type f -exec chmod 0644 {} \;
Если в системе нет nogroup, используй:
1
sudo chown -R nobody:nobody /srv/samba/public
Итог
Мы добавили публичную read-only шару:
1
\\nas\public
Она:
- доступна без пароля;
- работает только на чтение;
- отделена от рабочих и защищённых данных;
- не ломает текущие
[share]и[secure]; - подходит для общих файлов внутри локальной сети.
В следующей части займёмся самым важным для NAS — immutable backups на уровне Proxmox/ZFS.
