4 Commits

4 changed files with 234 additions and 111 deletions

238
install.sh Normal file → Executable file
View File

@@ -23,45 +23,119 @@ source "$LIB_DIR/backup.sh"
# ── Главное меню ───────────────────────────────────────────────────────────── # ── Главное меню ─────────────────────────────────────────────────────────────
show_main_menu() { show_main_menu() {
local proxy_status bot_status local proxy_status bot_status nginx_st mode domain secret port ip link ssl_expiry
proxy_status=$(telemt_status) proxy_status=$(telemt_status)
bot_status=$(bot_service_status) bot_status=$(bot_service_status)
nginx_st=$(nginx_status 2>/dev/null || echo "stopped")
mode=$(config_get mode 2>/dev/null || echo "—")
domain=$(config_get domain 2>/dev/null || echo "")
secret=$(get_config_value secret 2>/dev/null || echo "")
port=$(get_config_value port 2>/dev/null || echo "443")
ip=$(get_server_ip 2>/dev/null || echo "N/A")
local proxy_badge bot_badge local W=60
case "$proxy_status" in local line; line=$(printf '━%.0s' $(seq 1 $W))
running) proxy_badge="${GREEN}● Работает${NC}" ;; local line2; line2=$(printf '─%.0s' $(seq 1 $W))
stopped) proxy_badge="${YELLOW}○ Остановлен${NC}" ;;
*) proxy_badge="${RED}Не установлен${NC}" ;;
esac
case "$bot_status" in
running) bot_badge="${GREEN}● Бот работает${NC}" ;;
stopped) bot_badge="${YELLOW}○ Бот остановлен${NC}" ;;
*) bot_badge="${DIM}нет${NC}" ;;
esac
# ── Заголовок ──
echo "" echo ""
echo -e " ${BOLD}${WHITE}Главное меню${NC} │ Proxy: ${proxy_badge}${bot_badge}" echo -e " ${BOLD}${CYAN}${line}${NC}"
echo -e " ${DIM}$(printf '─%.0s' {1..60})${NC}" echo -e " ${BOLD}${CYAN}${NC} ${BOLD}${WHITE}GoTelegram v${GOTELEGRAM_VERSION}${NC} — Панель мониторинга ${BOLD}${CYAN}${NC}"
echo -e " ${DIM}── Прокси ──${NC}" echo -e " ${BOLD}${CYAN}${line}${NC}"
echo -e " ${CYAN} 1)${NC} 🔧 Установить / Обновить прокси"
echo -e " ${CYAN} 2)${NC} 📊 Статус" # ── Здоровье сервисов ──
echo -e " ${CYAN} 3)${NC} 🔗 Ссылка для подключения" echo ""
echo -e " ${CYAN} 4)${NC} 📤 Поделиться ключом" echo -e " ${DIM}${line2}${NC}"
echo -e " ${CYAN} 5)${NC} 🔄 Перезапуск"
echo -e " ${CYAN} 6)${NC} 📋 Логи" # Proxy
echo -e " ${CYAN} 7)${NC} 🎭 Сменить режим / шаблон" local proxy_icon proxy_color
echo -e " ${DIM}── Управление ──${NC}" case "$proxy_status" in
echo -e " ${CYAN} 8)${NC} 💾 Бекап конфигурации" running) proxy_icon="●"; proxy_color="${GREEN}" ;;
echo -e " ${CYAN} 9)${NC} 📦 Восстановить из бекапа" stopped) proxy_icon="○"; proxy_color="${YELLOW}" ;;
echo -e " ${CYAN}10)${NC} ⬆️ Обновить telemt" *) proxy_icon="✗"; proxy_color="${RED}" ;;
echo -e " ${CYAN}11)${NC} 🌐 Управление сайтом (SSL)" esac
echo -e " ${DIM}── Бот и прочее ──${NC}" echo -e " ${proxy_color}${proxy_icon}${NC} Прокси ${proxy_color}${proxy_status}${NC} ${DIM}(telemt ${mode})${NC}"
echo -e " ${CYAN}12)${NC} 🤖 Telegram-бот"
echo -e " ${CYAN}13)${NC} 🗑 Удалить всё" # nginx
echo -e " ${CYAN}14)${NC} 🏷 Промо" local nginx_icon nginx_color
echo -e " ${CYAN} 0)${NC} 🚪 Выход" case "$nginx_st" in
echo -e " ${DIM}$(printf '─%.0s' {1..60})${NC}" running) nginx_icon="●"; nginx_color="${GREEN}" ;;
echo -ne " ${WHITE}Выбор:${NC} " *) nginx_icon="✗"; nginx_color="${RED}" ;;
esac
echo -e " ${nginx_color}${nginx_icon}${NC} nginx ${nginx_color}${nginx_st}${NC} ${DIM}(127.0.0.1:8443)${NC}"
# Site (stealth)
if [ "$mode" = "stealth" ] && [ -n "$domain" ]; then
local site_icon site_color
if curl -sk --max-time 3 "https://${domain}/" -o /dev/null 2>/dev/null; then
site_icon="●"; site_color="${GREEN}"
else
site_icon="✗"; site_color="${RED}"
fi
echo -e " ${site_color}${site_icon}${NC} Сайт ${site_color}https://${domain}${NC}"
ssl_expiry=$(get_ssl_expiry "$domain" 2>/dev/null || echo "N/A")
echo -e " ${GREEN}${NC} SSL ${DIM}до ${ssl_expiry}${NC}"
fi
# Bot
case "$bot_status" in
running) echo -e " ${GREEN}${NC} Бот ${GREEN}running${NC}" ;;
stopped) echo -e " ${YELLOW}${NC} Бот ${YELLOW}stopped${NC}" ;;
esac
echo -e " ${DIM}${line2}${NC}"
# ── Сетевые параметры ──
echo -e " ${WHITE}IP:${NC} ${CYAN}${ip}${NC} ${WHITE}Порт:${NC} ${CYAN}${port}${NC} ${WHITE}Режим:${NC} ${CYAN}${mode}${NC}"
if [ -n "$domain" ]; then
echo -e " ${WHITE}Домен:${NC} ${CYAN}${domain}${NC}"
fi
echo -e " ${DIM}${line2}${NC}"
# ── Прокси-ссылка + QR ──
if [ -n "$secret" ] && [ "$proxy_status" = "running" ]; then
if [ "$mode" = "stealth" ] && [ -n "$domain" ]; then
local raw_secret faketls_secret domain_hex
raw_secret="$secret"
domain_hex=$(printf '%s' "$domain" | xxd -p | tr -d '\n')
faketls_secret="ee${raw_secret}${domain_hex}"
link="tg://proxy?server=${domain}&port=${port}&secret=${faketls_secret}"
else
link="tg://proxy?server=${ip}&port=${port}&secret=${secret}"
fi
echo -e " ${BOLD}${WHITE}Ссылка для Telegram:${NC}"
echo -e " ${GREEN}${link}${NC}"
echo ""
if command -v qrencode &>/dev/null; then
qrencode -t UTF8 -m 1 "$link" 2>/dev/null | while IFS= read -r qr_line; do
echo " ${qr_line}"
done
echo ""
fi
else
echo -e " ${DIM}Прокси не настроен. Выберите п.1 для установки.${NC}"
echo ""
fi
# ── Меню ──
echo -e " ${DIM}${line2}${NC}"
echo -e " ${DIM}ПРОКСИ${NC} ${DIM}УПРАВЛЕНИЕ${NC}"
echo -e " ${CYAN}1${NC}) Установить / Обновить ${CYAN}8${NC}) Бекап"
echo -e " ${CYAN}2${NC}) Статус подробно ${CYAN}9${NC}) Восстановить"
echo -e " ${CYAN}3${NC}) Скопировать ссылку ${CYAN}10${NC}) Обновить telemt"
echo -e " ${CYAN}4${NC}) Поделиться ключом ${CYAN}11${NC}) Сайт / SSL"
echo -e " ${CYAN}5${NC}) Перезапуск"
echo -e " ${CYAN}6${NC}) Логи ${DIM}БОТ И ПРОЧЕЕ${NC}"
echo -e " ${CYAN}7${NC}) Сменить режим / шаблон ${CYAN}12${NC}) Telegram-бот"
echo -e " ${CYAN}13${NC}) Удалить всё"
echo -e " ${CYAN}0${NC}) ${DIM}Выход${NC} ${CYAN}14${NC}) Промо"
echo -e " ${DIM}${line2}${NC}"
echo -e " ${DIM}Обновление через 30 сек${NC}"
echo -ne " ${WHITE}${NC}"
} }
# ── Установка: выбор режима ────────────────────────────────────────────────── # ── Установка: выбор режима ──────────────────────────────────────────────────
@@ -192,24 +266,32 @@ install_stealth_mode() {
template_dir=$(interactive_template_selection) template_dir=$(interactive_template_selection)
[ $? -ne 0 ] && return [ $? -ne 0 ] && return
# Внутренний порт для telemt (только localhost, не открыт наружу) # Архитектура Stealth:
# nginx принимает весь трафик на внешнем 443 и проксирует MTProxy-соединения на localhost:8443 # telemt слушает на 0.0.0.0:443 (принимает ВСЕ подключения)
# Внешний порт 8443 НЕ затрагивается и НЕ открывается — telemt слушает только 127.0.0.1 # nginx слушает на 127.0.0.1:8443 с SSL (обслуживает сайт)
local telemt_port=8443 # MTProxy клиент → :443 → telemt (проксирует)
# Обычный браузер → :443 → telemt → 127.0.0.1:8443 → nginx (сайт)
# Провайдер видит только HTTPS на 443 к домену
local nginx_internal_port=8443
echo "" echo ""
echo -e " ${DIM}telemt будет слушать на localhost:$telemt_port (только внутренний, не открыт наружу)${NC}" echo -e " ${DIM}telemt принимает весь трафик на 443 (маскировка под HTTPS)${NC}"
echo -e " ${DIM}nginx принимает трафик на 443 (внешний) и проксирует к telemt${NC}" echo -e " ${DIM}nginx обслуживает сайт на внутреннем порту $nginx_internal_port${NC}"
echo -e " ${DIM}Провайдер видит только HTTPS-трафик к ${user_domain}:443${NC}"
# Генерация секрета # Генерация fake-TLS секрета (ee + secret + hex domain)
local secret # Префикс ee говорит Telegram-клиенту маскировать трафик под TLS к домену
secret=$(generate_hex 32) local raw_secret
raw_secret=$(generate_hex 32)
local domain_hex
domain_hex=$(printf '%s' "$user_domain" | xxd -p | tr -d '\n')
local faketls_secret="ee${raw_secret}${domain_hex}"
# Подтверждение # Подтверждение
echo "" echo ""
echo -e " ${BOLD}${WHITE}📋 Конфигурация:${NC}" echo -e " ${BOLD}${WHITE}📋 Конфигурация:${NC}"
echo -e " Домен: ${CYAN}${user_domain}${NC}" echo -e " Домен: ${CYAN}${user_domain}${NC}"
echo -e " Порт: ${CYAN}443 (nginx) → $telemt_port (telemt)${NC}" echo -e " Порт: ${CYAN}443 (telemt + nginx внутри)${NC}"
echo -e " Режим: ${MAGENTA}Stealth${NC}" echo -e " Режим: ${MAGENTA}Stealth (fake-TLS)${NC}"
echo "" echo ""
if ! confirm "Установить прокси + сайт?"; then if ! confirm "Установить прокси + сайт?"; then
@@ -220,11 +302,15 @@ install_stealth_mode() {
ensure_deps ensure_deps
install_telemt_full || return install_telemt_full || return
# Конфиг telemt: маскировка на localhost (nginx) # Конфиг telemt: слушает 443, маскировка на локальный nginx через dns_override
generate_telemt_toml "$secret" "$telemt_port" "stealth" "127.0.0.1" "443" generate_telemt_toml "$raw_secret" "443" "stealth" "$user_domain" "$nginx_internal_port"
# Настройка сайта (nginx + certbot + шаблон) # Настройка сайта (nginx на внутреннем порту + certbot + шаблон)
setup_stealth_mode "$user_domain" "$template_dir" "$telemt_port" "$ssl_email" || return setup_stealth_mode "$user_domain" "$template_dir" "$nginx_internal_port" "$ssl_email" || return
# Останавливаем nginx на 443 перед запуском telemt (telemt займёт 443)
# nginx уже перенастроен на внутренний порт
systemctl restart nginx 2>/dev/null
# Запуск telemt # Запуск telemt
start_telemt || return start_telemt || return
@@ -232,10 +318,10 @@ install_stealth_mode() {
# Сохраняем конфиг # Сохраняем конфиг
local tpl_id local tpl_id
tpl_id=$(basename "$template_dir") tpl_id=$(basename "$template_dir")
save_gotelegram_config "telemt" "stealth" "443" "$secret" "127.0.0.1" "$user_domain" "$tpl_id" save_gotelegram_config "telemt" "stealth" "443" "$raw_secret" "$user_domain" "$user_domain" "$tpl_id"
# Результат # Результат — используем домен и fake-TLS ссылку
show_proxy_info show_proxy_info_stealth "$user_domain" "$faketls_secret"
echo -e " ${WHITE}Сайт:${NC} ${GREEN}https://${user_domain}${NC}" echo -e " ${WHITE}Сайт:${NC} ${GREEN}https://${user_domain}${NC}"
log_success "GoTelegram v${GOTELEGRAM_VERSION} установлен! (Stealth-режим)" log_success "GoTelegram v${GOTELEGRAM_VERSION} установлен! (Stealth-режим)"
} }
@@ -754,30 +840,34 @@ main() {
check_disk_space 500 check_disk_space 500
while true; do while true; do
clear
show_main_menu show_main_menu
read -r choice # Auto-refresh: 30 sec timeout
case "$choice" in if read -t 30 -r choice; then
1) menu_install ;; case "$choice" in
2) menu_status ;; 1) menu_install ;;
3) menu_link ;; 2) menu_status ;;
4) menu_share ;; 3) menu_link ;;
5) menu_restart ;; 4) menu_share ;;
6) menu_logs ;; 5) menu_restart ;;
7) menu_change_mode ;; 6) menu_logs ;;
8) interactive_backup ;; 7) menu_change_mode ;;
9) interactive_restore ;; 8) interactive_backup ;;
10) update_telemt ;; 9) interactive_restore ;;
11) menu_website ;; 10) update_telemt ;;
12) menu_bot ;; 11) menu_website ;;
13) menu_remove ;; 12) menu_bot ;;
14) menu_promo ;; 13) menu_remove ;;
0|q|exit) echo ""; log_info "До встречи! 👋"; exit 0 ;; 14) menu_promo ;;
*) log_error "Неверный выбор" ;; 0|q|exit) echo ""; log_info "До встречи! 👋"; exit 0 ;;
esac *) log_error "Неверный выбор" ;;
esac
echo "" echo ""
echo -ne " ${DIM}Нажмите Enter для возврата в меню...${NC}" echo -ne " ${DIM}Нажмите Enter для возврата в меню...${NC}"
read -r read -r
fi
# If read timed out, loop refreshes the dashboard
done done
} }

View File

@@ -174,9 +174,8 @@ LimitNOFILE=65535
# Безопасность # Безопасность
NoNewPrivileges=true NoNewPrivileges=true
ProtectSystem=strict ProtectSystem=full
ProtectHome=true ProtectHome=true
ReadWritePaths=/etc/telemt /var/log
PrivateTmp=true PrivateTmp=true
[Install] [Install]

View File

@@ -25,52 +25,49 @@ QUICK_DOMAINS=(
"zoom.us" "zoom.us"
) )
# ── Генерация TOML конфига ─────────────────────────────────────────────────── # ── Генерация TOML конфига (telemt v3 формат) ───────────────────────────────
generate_telemt_toml() { generate_telemt_toml() {
local secret="$1" local secret="$1"
local port="${2:-443}" local port="${2:-443}"
local mask_mode="${3:-quick}" # quick | stealth local mask_mode="${3:-quick}" # quick | stealth
local mask_host="${4:-google.com}" local mask_domain="${4:-google.com}"
local mask_port="${5:-443}" local mask_port="${5:-443}"
local output="${6:-$TELEMT_CONFIG}" local output="${6:-$TELEMT_CONFIG}"
mkdir -p "$(dirname "$output")" mkdir -p "$(dirname "$output")"
# В stealth-режиме telemt слушает только localhost (трафик идёт через nginx) # DNS override для stealth: домен резолвится в 127.0.0.1
# В quick-режиме — на всех интерфейсах (клиенты подключаются напрямую) # чтобы mask-трафик шёл на локальный nginx, а не в интернет
local bind_addr="0.0.0.0" local dns_line=""
[ "$mask_mode" = "stealth" ] && bind_addr="127.0.0.1" if [ "$mask_mode" = "stealth" ]; then
dns_line="dns_overrides = [\"${mask_domain}:${mask_port}:127.0.0.1\"]"
fi
cat > "$output" << EOTOML cat > "$output" << EOTOML
# GoTelegram v${GOTELEGRAM_VERSION} — telemt configuration # GoTelegram v${GOTELEGRAM_VERSION} — telemt v3 configuration
# Сгенерировано: $(date -Iseconds) # Сгенерировано: $(date -Iseconds)
# Режим: ${mask_mode} # Режим: ${mask_mode}
# ── Основные настройки ─────────────────────────────────────────────────────── [server]
[stats] port = ${port}
statsd_address = "" listen_addr_ipv4 = "0.0.0.0"
# ── Секреты ────────────────────────────────────────────────────────────────── [censorship]
[[users]] tls_domain = "${mask_domain}"
name = "main" mask = true
secret = "${secret}" mask_port = ${mask_port}
tls_emulation = $([ "$mask_mode" = "stealth" ] && echo "false" || echo "true")
# ── Привязка ───────────────────────────────────────────────────────────────── [access.users]
[listen] main = "${secret}"
# quick: 0.0.0.0 (клиенты напрямую) | stealth: 127.0.0.1 (только через nginx)
bind_to = "${bind_addr}:${port}"
# ── TLS маскировка ───────────────────────────────────────────────────────────
[security]
# Маскировочный хост — куда перенаправлять неопознанные подключения
# quick: внешний сайт | stealth: локальный nginx
host = "${mask_host}:${mask_port}"
[network]
${dns_line}
EOTOML EOTOML
chmod 600 "$output" chmod 600 "$output"
log_success "Конфиг telemt записан: $output" log_success "Конфиг telemt записан: $output"
log_dim "Режим: $mask_mode, маскировка: $mask_host:$mask_port" log_dim "Режим: $mask_mode, домен: $mask_domain, порт mask: $mask_port"
} }
# ── Добавление дополнительного секрета ─────────────────────────────────────── # ── Добавление дополнительного секрета ───────────────────────────────────────
@@ -95,7 +92,7 @@ EOSECRET
log_success "Добавлен секрет: $name" log_success "Добавлен секрет: $name"
} }
# ── Чтение текущего конфига ────────────────────────────────────────────────── # ── Чтение текущего конфига (telemt v3 формат) ──────────────────────────────
get_config_value() { get_config_value() {
local key="$1" local key="$1"
local config="${2:-$TELEMT_CONFIG}" local config="${2:-$TELEMT_CONFIG}"
@@ -104,13 +101,19 @@ get_config_value() {
case "$key" in case "$key" in
secret) secret)
grep -m1 'secret\s*=' "$config" | sed 's/.*=\s*"\(.*\)"/\1/' | tr -d ' ' # [access.users] main = "..."
grep -A5 '\[access.users\]' "$config" | grep -m1 '=' | sed 's/.*=\s*"\(.*\)"/\1/' | tr -d ' '
;; ;;
port) port)
grep 'bind_to\s*=' "$config" | sed 's/.*:\([0-9]*\)".*/\1/' # [server] port = 443
grep -A5 '\[server\]' "$config" | grep 'port\s*=' | head -1 | sed 's/.*=\s*\([0-9]*\)/\1/' | tr -d ' '
;; ;;
mask_host) mask_host|tls_domain)
grep -A10 '\[security\]' "$config" | grep 'host\s*=' | sed 's/.*=\s*"\(.*\)".*/\1/' # [censorship] tls_domain = "..."
grep -A10 '\[censorship\]' "$config" | grep 'tls_domain\s*=' | sed 's/.*=\s*"\(.*\)"/\1/'
;;
mask_port)
grep -A10 '\[censorship\]' "$config" | grep 'mask_port\s*=' | sed 's/.*=\s*\([0-9]*\)/\1/' | tr -d ' '
;; ;;
*) *)
grep "$key" "$config" | head -1 | sed 's/.*=\s*"\?\(.*\)"\?/\1/' | tr -d ' "' grep "$key" "$config" | head -1 | sed 's/.*=\s*"\?\(.*\)"\?/\1/' | tr -d ' "'
@@ -151,7 +154,7 @@ validate_telemt_config() {
fi fi
if [ -z "$host" ]; then if [ -z "$host" ]; then
log_error "Не задан маскировочный хост (security.host)" log_error "Не задан маскировочный хост (censorship.tls_domain)"
((errors++)) ((errors++))
fi fi
@@ -286,3 +289,34 @@ show_proxy_info() {
qrencode -t UTF8 -m 2 "$link" 2>/dev/null qrencode -t UTF8 -m 2 "$link" 2>/dev/null
fi fi
} }
# ── Вывод информации о прокси (Stealth-режим) ──────────────────────────────
# В stealth-режиме ссылка содержит домен (не IP) и fake-TLS секрет (ee...)
show_proxy_info_stealth() {
local domain="$1"
local faketls_secret="$2"
local link="tg://proxy?server=${domain}&port=443&secret=${faketls_secret}"
echo ""
echo -e " ${BOLD}${WHITE}✅ Stealth-прокси настроен${NC}"
echo -e " ${DIM}$(printf '─%.0s' {1..55})${NC}"
echo -e " ${WHITE}Ядро:${NC} telemt (Rust)"
echo -e " ${WHITE}Домен:${NC} ${CYAN}${domain}${NC}"
echo -e " ${WHITE}Порт:${NC} ${CYAN}443${NC} (внешний, telemt)"
echo -e " ${WHITE}Режим:${NC} ${MAGENTA}Stealth (fake-TLS)${NC}"
echo -e " ${WHITE}nginx:${NC} ${CYAN}127.0.0.1:8443${NC} (внутренний)"
echo -e " ${WHITE}Secret:${NC} ${CYAN}${faketls_secret:0:20}...${NC}"
echo -e " ${DIM}$(printf '─%.0s' {1..55})${NC}"
echo -e " ${WHITE}Ссылка для Telegram:${NC}"
echo -e " ${GREEN}${link}${NC}"
echo ""
echo -e " ${DIM}Провайдер видит: HTTPS-трафик к ${domain}:443${NC}"
echo -e " ${DIM}Telegram-клиент маскирует соединение под TLS${NC}"
echo ""
# QR если доступен
if command -v qrencode &>/dev/null; then
qrencode -t UTF8 -m 2 "$link" 2>/dev/null
fi
}

View File

@@ -40,7 +40,8 @@ generate_nginx_config() {
cat > "$NGINX_SITE_CONF" << 'EONGINX' cat > "$NGINX_SITE_CONF" << 'EONGINX'
# GoTelegram v2.2 — nginx config # GoTelegram v2.2 — nginx config
# Обслуживает сайт-маскировку для telemt stealth mode # Stealth: nginx на 127.0.0.1:8443 (внутренний), telemt на 0.0.0.0:443 (внешний)
# Обычный браузер → :443 → telemt → 127.0.0.1:8443 → nginx (сайт)
server { server {
listen 80; listen 80;
@@ -60,8 +61,7 @@ server {
} }
server { server {
listen SSL_PORT_PLACEHOLDER ssl http2; listen 127.0.0.1:SSL_PORT_PLACEHOLDER ssl http2;
listen [::]:SSL_PORT_PLACEHOLDER ssl http2;
server_name DOMAIN_PLACEHOLDER; server_name DOMAIN_PLACEHOLDER;
# SSL сертификаты # SSL сертификаты
@@ -113,7 +113,7 @@ EONGINX
local escaped_domain local escaped_domain
escaped_domain=$(printf '%s\n' "$domain" | sed 's/[&/\]/\\&/g') escaped_domain=$(printf '%s\n' "$domain" | sed 's/[&/\]/\\&/g')
sed -i "s|DOMAIN_PLACEHOLDER|${escaped_domain}|g" "$NGINX_SITE_CONF" sed -i "s|DOMAIN_PLACEHOLDER|${escaped_domain}|g" "$NGINX_SITE_CONF"
sed -i "s|SSL_PORT_PLACEHOLDER|443|g" "$NGINX_SITE_CONF" sed -i "s|SSL_PORT_PLACEHOLDER|${proxy_port}|g" "$NGINX_SITE_CONF"
# Активируем сайт # Активируем сайт
rm -f /etc/nginx/sites-enabled/default 2>/dev/null rm -f /etc/nginx/sites-enabled/default 2>/dev/null