mirror of
https://github.com/andrey271192/PCAtelegram_web.git
synced 2026-09-20 11:55:32 +00:00
feat: expose web admin with auth by default
This commit is contained in:
29
README.md
29
README.md
@@ -50,33 +50,32 @@ ssh root@SERVER 'chmod +x /opt/pcatelegram_web/install.sh /opt/pcatelegram_web/i
|
||||
| `PCATELEGRAM_WEB_BASE` | `https://raw.githubusercontent.com/andrey271192/PCAtelegram_web/main` | база загрузки файлов |
|
||||
| `PCATELEGRAM_WEB_INSTALL_DIR` | `/opt/pcatelegram_web` | путь установки |
|
||||
| `GITHUB_TOKEN` / `GH_TOKEN` | пусто | token для private GitHub raw downloads |
|
||||
| `PCATELEGRAM_WEB_ADMIN_HOST` | `127.0.0.1` | bind web-admin |
|
||||
| `PCATELEGRAM_WEB_ADMIN_HOST` | `0.0.0.0` | bind web-admin |
|
||||
| `PCATELEGRAM_WEB_ADMIN_PORT` | `1984` | port web-admin |
|
||||
| `PCATELEGRAM_WEB_ADMIN_USER` | `admin` | Basic Auth login |
|
||||
| `PCATELEGRAM_WEB_ADMIN_PASSWORD` | пусто | Basic Auth password; обязателен при public bind |
|
||||
| `PCATELEGRAM_WEB_ADMIN_PASSWORD` | автогенерация | Basic Auth password |
|
||||
|
||||
## Web-admin
|
||||
|
||||
После первого запуска `pcatelegram_web` локальная web-admin панель ставится как `pcatelegram_web-admin.service`.
|
||||
|
||||
Безопасный локальный доступ через SSH tunnel:
|
||||
После первого запуска `pcatelegram_web` web-admin панель ставится как `pcatelegram_web-admin.service` и слушает публично:
|
||||
|
||||
```bash
|
||||
ssh -L 1984:127.0.0.1:1984 root@SERVER
|
||||
open http://127.0.0.1:1984/
|
||||
http://SERVER:1984/
|
||||
```
|
||||
|
||||
Для public bind сначала задайте пароль через systemd override или reverse proxy:
|
||||
Логин по умолчанию: `admin`. Пароль генерируется при установке и хранится на сервере:
|
||||
|
||||
```ini
|
||||
[Service]
|
||||
Environment=PCATELEGRAM_WEB_ADMIN_HOST=0.0.0.0
|
||||
Environment=PCATELEGRAM_WEB_ADMIN_PORT=1984
|
||||
Environment=PCATELEGRAM_WEB_ADMIN_USER=admin
|
||||
Environment=PCATELEGRAM_WEB_ADMIN_PASSWORD=change-me
|
||||
```bash
|
||||
sudo cat /root/pcatelegram_web-admin.password
|
||||
```
|
||||
|
||||
Без HTTPS public Basic Auth гонит пароль открытым текстом. Для постоянного доступа лучше reverse proxy с TLS.
|
||||
Для своего пароля передайте env до установки:
|
||||
|
||||
```bash
|
||||
PCATELEGRAM_WEB_ADMIN_PASSWORD='strong-password' bash bootstrap.sh
|
||||
```
|
||||
|
||||
Без HTTPS Basic Auth гонит пароль открытым текстом. Для постоянного доступа лучше reverse proxy с TLS, но порт `1984` открыт по умолчанию по запросу проекта.
|
||||
|
||||
## Проверки
|
||||
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
"""
|
||||
PCAtelegram_web local web admin.
|
||||
|
||||
The service is intentionally bound to 127.0.0.1:1984. Operators reach it
|
||||
through an SSH tunnel by default. If exposed through a reverse proxy or public
|
||||
bind, enable PCATELEGRAM_WEB_ADMIN_PASSWORD.
|
||||
The service is publicly reachable by default and protected with Basic Auth.
|
||||
Installers generate /root/pcatelegram_web-admin.password for credentials.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -49,7 +48,7 @@ SHARED_443_CONFIG = Path(os.getenv("PCATELEGRAM_WEB_SHARED_443", "/opt/pcatelegr
|
||||
BACKUP_SCHEDULE_FILE = Path(os.getenv("PCATELEGRAM_WEB_BACKUP_SCHEDULE", "/opt/pcatelegram_web/backup_schedule.json"))
|
||||
BACKUP_RESTORE_LOG = Path(os.getenv("PCATELEGRAM_WEB_BACKUP_RESTORE_LOG", "/var/log/pcatelegram_web-restore.log"))
|
||||
|
||||
HOST = os.getenv("PCATELEGRAM_WEB_ADMIN_HOST", "127.0.0.1")
|
||||
HOST = os.getenv("PCATELEGRAM_WEB_ADMIN_HOST", "0.0.0.0")
|
||||
PORT = int(os.getenv("PCATELEGRAM_WEB_ADMIN_PORT", "1984"))
|
||||
ADMIN_USER = os.getenv("PCATELEGRAM_WEB_ADMIN_USER", "admin")
|
||||
ADMIN_PASSWORD = os.getenv("PCATELEGRAM_WEB_ADMIN_PASSWORD", "")
|
||||
@@ -70,6 +69,17 @@ TRAFFIC_WINDOWS = {
|
||||
}
|
||||
|
||||
|
||||
def load_admin_password_file() -> str:
|
||||
path = Path(os.getenv("PCATELEGRAM_WEB_ADMIN_AUTH_FILE", "/root/pcatelegram_web-admin.password"))
|
||||
try:
|
||||
for line in path.read_text(encoding="utf-8").splitlines():
|
||||
if line.startswith("password="):
|
||||
return line.split("=", 1)[1].strip()
|
||||
except OSError:
|
||||
return ""
|
||||
return ""
|
||||
|
||||
|
||||
def utc_now() -> str:
|
||||
return datetime.now(timezone.utc).isoformat()
|
||||
|
||||
@@ -1288,7 +1298,7 @@ class AdminHandler(BaseHTTPRequestHandler):
|
||||
print("%s - %s" % (self.address_string(), fmt % args))
|
||||
|
||||
def auth_enabled(self) -> bool:
|
||||
return bool(ADMIN_PASSWORD)
|
||||
return bool(ADMIN_PASSWORD or load_admin_password_file())
|
||||
|
||||
def is_authorized(self) -> bool:
|
||||
if not self.auth_enabled():
|
||||
@@ -1301,7 +1311,8 @@ class AdminHandler(BaseHTTPRequestHandler):
|
||||
username, password = decoded.split(":", 1)
|
||||
except Exception:
|
||||
return False
|
||||
return hmac.compare_digest(username, ADMIN_USER) and hmac.compare_digest(password, ADMIN_PASSWORD)
|
||||
expected_password = ADMIN_PASSWORD or load_admin_password_file()
|
||||
return hmac.compare_digest(username, ADMIN_USER) and hmac.compare_digest(password, expected_password)
|
||||
|
||||
def require_auth(self) -> bool:
|
||||
if self.is_authorized():
|
||||
|
||||
@@ -902,8 +902,9 @@ install_admin_web() {
|
||||
chmod 755 "$ADMIN_WEB_DIR/server.py" "$ADMIN_WEB_DIR/static"
|
||||
rm -f "$ADMIN_WEB_DIR/token" 2>/dev/null || true
|
||||
|
||||
local python_bin
|
||||
local python_bin admin_password
|
||||
python_bin=$(command -v python3)
|
||||
admin_password=$(ensure_admin_web_password)
|
||||
cat > "/etc/systemd/system/${ADMIN_WEB_SERVICE}.service" << SVCEOF
|
||||
[Unit]
|
||||
Description=PCAtelegram_web v${PCATELEGRAM_WEB_VERSION} Local Web Admin
|
||||
@@ -917,6 +918,8 @@ Restart=always
|
||||
RestartSec=5
|
||||
Environment=PCATELEGRAM_WEB_ADMIN_HOST=$ADMIN_WEB_HOST
|
||||
Environment=PCATELEGRAM_WEB_ADMIN_PORT=$ADMIN_WEB_PORT
|
||||
Environment=PCATELEGRAM_WEB_ADMIN_USER=${PCATELEGRAM_WEB_ADMIN_USER:-admin}
|
||||
Environment=PCATELEGRAM_WEB_ADMIN_PASSWORD=$admin_password
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -928,7 +931,8 @@ SVCEOF
|
||||
if type install_stats_collector &>/dev/null; then
|
||||
install_stats_collector >/dev/null 2>&1 || log_warning "stats collector was not started; open Web Admin traffic page and use Repair"
|
||||
fi
|
||||
log_success "Web admin installed: ${ADMIN_WEB_HOST}:${ADMIN_WEB_PORT}"
|
||||
log_success "Web admin installed: http://$(get_server_ip):${ADMIN_WEB_PORT}/"
|
||||
log_info "Web admin login saved: $ADMIN_WEB_AUTH_FILE"
|
||||
}
|
||||
|
||||
auto_install_admin_web_if_possible() {
|
||||
|
||||
@@ -15,6 +15,32 @@ PCATELEGRAM_WEB_DIR="/opt/pcatelegram_web"
|
||||
ADMIN_WEB_DIR="/opt/pcatelegram_web-admin"
|
||||
ADMIN_WEB_SERVICE="pcatelegram_web-admin"
|
||||
ADMIN_WEB_PORT="1984"
|
||||
ADMIN_WEB_HOST="0.0.0.0"
|
||||
ADMIN_WEB_AUTH_FILE="/root/pcatelegram_web-admin.password"
|
||||
|
||||
ensure_admin_web_password() {
|
||||
local pw=""
|
||||
if [ -n "${PCATELEGRAM_WEB_ADMIN_PASSWORD:-}" ]; then
|
||||
pw="$PCATELEGRAM_WEB_ADMIN_PASSWORD"
|
||||
elif [ -f "$ADMIN_WEB_AUTH_FILE" ] && [ -s "$ADMIN_WEB_AUTH_FILE" ]; then
|
||||
pw=$(sed -n 's/^password=//p' "$ADMIN_WEB_AUTH_FILE" | head -1)
|
||||
fi
|
||||
if [ -z "$pw" ]; then
|
||||
if command -v openssl >/dev/null 2>&1; then
|
||||
pw=$(openssl rand -base64 24 | tr -d '\n')
|
||||
else
|
||||
pw=$(head -c 24 /dev/urandom | base64 | tr -d '\n')
|
||||
fi
|
||||
fi
|
||||
umask 077
|
||||
cat > "$ADMIN_WEB_AUTH_FILE" <<EOF
|
||||
user=${PCATELEGRAM_WEB_ADMIN_USER:-admin}
|
||||
password=${pw}
|
||||
url=http://$(hostname -I 2>/dev/null | awk '{print $1}'):${ADMIN_WEB_PORT}/
|
||||
EOF
|
||||
chmod 600 "$ADMIN_WEB_AUTH_FILE" 2>/dev/null || true
|
||||
printf '%s' "$pw"
|
||||
}
|
||||
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo -e "${RED}Запустите с sudo.${NC}"
|
||||
@@ -128,6 +154,7 @@ if [ -f "$SCRIPT_DIR/admin-web/server.py" ]; then
|
||||
rm -f "$ADMIN_WEB_DIR/token" 2>/dev/null || true
|
||||
|
||||
PYTHON_BIN=$(command -v python3)
|
||||
ADMIN_WEB_PASSWORD=$(ensure_admin_web_password)
|
||||
cat > "/etc/systemd/system/${ADMIN_WEB_SERVICE}.service" << EOF
|
||||
[Unit]
|
||||
Description=PCAtelegram_web v2.5.0 Local Web Admin
|
||||
@@ -139,8 +166,10 @@ WorkingDirectory=$ADMIN_WEB_DIR
|
||||
ExecStart=$PYTHON_BIN $ADMIN_WEB_DIR/server.py
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
Environment=PCATELEGRAM_WEB_ADMIN_HOST=127.0.0.1
|
||||
Environment=PCATELEGRAM_WEB_ADMIN_HOST=$ADMIN_WEB_HOST
|
||||
Environment=PCATELEGRAM_WEB_ADMIN_PORT=$ADMIN_WEB_PORT
|
||||
Environment=PCATELEGRAM_WEB_ADMIN_USER=${PCATELEGRAM_WEB_ADMIN_USER:-admin}
|
||||
Environment=PCATELEGRAM_WEB_ADMIN_PASSWORD=$ADMIN_WEB_PASSWORD
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -20,8 +20,9 @@ LOG_FILE="/var/log/pcatelegram_web.log"
|
||||
BOT_DIR="/opt/pcatelegram_web-bot"
|
||||
ADMIN_WEB_DIR="/opt/pcatelegram_web-admin"
|
||||
ADMIN_WEB_SERVICE="pcatelegram_web-admin"
|
||||
ADMIN_WEB_HOST="127.0.0.1"
|
||||
ADMIN_WEB_HOST="0.0.0.0"
|
||||
ADMIN_WEB_PORT="1984"
|
||||
ADMIN_WEB_AUTH_FILE="/root/pcatelegram_web-admin.password"
|
||||
|
||||
# ── V1 совместимость ─────────────────────────────────────────────────────────
|
||||
V1_CONTAINER_NAME="mtproto-proxy"
|
||||
@@ -738,3 +739,29 @@ init_dirs() {
|
||||
mkdir -p "$PCATELEGRAM_WEB_DIR" "$BACKUP_DIR" /etc/telemt 2>/dev/null
|
||||
touch "$LOG_FILE" 2>/dev/null
|
||||
}
|
||||
|
||||
ensure_admin_web_password() {
|
||||
local pw=""
|
||||
if [ -n "${PCATELEGRAM_WEB_ADMIN_PASSWORD:-}" ]; then
|
||||
pw="$PCATELEGRAM_WEB_ADMIN_PASSWORD"
|
||||
elif [ -f "$ADMIN_WEB_AUTH_FILE" ] && [ -s "$ADMIN_WEB_AUTH_FILE" ]; then
|
||||
pw=$(sed -n 's/^password=//p' "$ADMIN_WEB_AUTH_FILE" | head -1)
|
||||
fi
|
||||
|
||||
if [ -z "$pw" ]; then
|
||||
if command -v openssl >/dev/null 2>&1; then
|
||||
pw=$(openssl rand -base64 24 | tr -d '\n')
|
||||
else
|
||||
pw=$(head -c 24 /dev/urandom | base64 | tr -d '\n')
|
||||
fi
|
||||
fi
|
||||
|
||||
umask 077
|
||||
cat > "$ADMIN_WEB_AUTH_FILE" <<EOF
|
||||
user=${PCATELEGRAM_WEB_ADMIN_USER:-admin}
|
||||
password=${pw}
|
||||
url=http://$(get_server_ip 2>/dev/null || hostname -I 2>/dev/null | awk '{print $1}'):${ADMIN_WEB_PORT}/
|
||||
EOF
|
||||
chmod 600 "$ADMIN_WEB_AUTH_FILE" 2>/dev/null || true
|
||||
printf '%s' "$pw"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user