Syno NAS: sao chép wildcard SSL

  • DSM có thể dùng Lets’s Encrypt tạo wildcard SSL certificate dùng chung cho domain và tất cả các subdomain, tuy nhiên chỉ áp dụng cho domain thuộc Synology.
  • SSL certificate của Synology có hạn dùng 1 năm so với các free certificate khác có hạn dùng 3 tháng. Tuy nhiên vì có thể auto renew các chứng chỉ bảo mật nên hạn dùng không là vấn đề.
  • Có thể import SSL certificate từ nguồn khác vào DSM và chọn dùng cho từng dịch vụ web cụ thể.

Chúng ta có thể tạo wildcard SSL certificate của Let’s Encrypt từ máy tính khác như Raspberry Pi và import vào Synology NAS qua script.

Hoạt động của script như sau:

  • Theo dõi certbot renew. Nếu không có chứng chỉ SSL mới thì thoát
  • Chép chứng chỉ SSL mới cho tất cả các dịch vụ có dùng SSL trên Synology NAS
  • Nếu một dịch vụ được cài đặt dùng chứng chỉ SSL của Synology thì DSM tự phục hồi chứng chỉ Synology
  • Khởi động lại các dịch vụ có dùng SSL certificate
#!/bin/bash
# renew_certs.sh
# LNT <lnt@ly-le.info>
# -------------------
# domain cần update certs
DOMAIN='your.domain'
certbot -q renew --post-hook "touch /tmp/new_certs" &>/dev/null
[ ! -f /tmp/new_certs ] && exit

### Update NAS certs ###

NAS_SERVER='your_nas_ip'

# user có thể ssh tới NAS, có thể sudoer
SSL_USR="user@${NAS_SERVER}"
SSL_PORT=22

# script replace_certs.sh
REPLACE_CERTS='/path/to/replace_certs.sh'

# Nơi chứa certs
CERTS_DIRECTORY="/etc/letsencrypt/live/$DOMAIN"

echo "### Copying certificates to NAS ###"
scp -P ${SSL_PORT} ${CERTS_DIRECTORY}/{privkey,fullchain,cert}.pem ${SSL_USR}:/tmp/
if [ "$?" = "0" ]; then
  echo "### Copying script to NAS ###"
  scp -P ${SSL_PORT} ${REPLACE_CERTS} ${SSL_USR}:
  echo "### Updating certificates to NAS ###"
  ssh -p ${SSL_PORT} -t ${SSL_USR} 'sudo ./replace_certs.sh'
  if [ "$?" != "0" ]; then
    echo "--- ERROR Updating certificates to NAS ---"
  fi
else
  echo "--- ERROR Copying certificates to NAS ---"
fi
  • Script này được gọi chạy thay cho lệnh certbot renew thông thường. Thí dụ trong file /etc/cron.d/certbot, thay đoạn certbot renew -q thành /path/to/renew_certs.sh
  • SSL_USR phải có thể ssh đến NAS
  • Ngoài ra để có thể chạy script ${REPLACE_CERTS} trên NAS với quyền root thì ${SSL_USR} phải có thể sudoer
${SSL_USR} (ALL:ALL) ${REPLACE_CERTS}
# !/bin/bash
# replace_certs.sh
# Cải tiến script của catchdave, dành cho DSM 7.2
# LNT <lnt@ly-le.info>
# -------------------
DEBUG=0 # 0 or 1
error_exit() { echo "[ERROR] $1"; exit 1; }
warn() { echo "[WARN] $1"; }
info() { echo "[INFO] $1"; }
debug() { [[ "${DEBUG}" ]] && echo "[DEBUG] $1"; }

[[ "$EUID" -ne 0 ]] && error_exit "Please run as root!"
[ ! -f /tmp/cert.pem ] && error_exit "No new certs!"

services_to_restart=("nmbd" "avahi" "ldap-server")
packages_to_restart=()
syno_cert_dir='/usr/syno/etc/certificate'
certs_src_dir="$syno_cert_dir/system/default"
target_cert_dirs=( "$syno_cert_dir/system/FQDN" )

default_dir_name=$(cat $syno_cert_dir/_archive/DEFAULT 2>/dev/null)
if [[ -n "$default_dir_name" ]]; then
    target_cert_dirs+=( "$syno_cert_dir/_archive/${default_dir_name}" )
    (( $DEBUG )) && debug "Default cert directory found: '$syno_cert_dir/_archive/${default_dir_name}'"
else
    error_exit "No default directory found! See $syno_cert_dir/_archive/DEFAULT"
fi

mapfile -t tmp <<< $(find ${syno_cert_dir}/smbftpd -mindepth 1 -maxdepth 1 -type d 2>/dev/null)
if (( ${#tmp[@]} )); then
    target_cert_dirs+=( ${tmp[*]} )
    (( $DEBUG )) && debug "SMB or FTPD found!"
else
    warn "No SMB and FTPD found!"
fi

mapfile -t tmp <<< $(find ${syno_cert_dir}/AppPortal -mindepth 1 -maxdepth 1 -type d 2>/dev/null)
if (( ${#tmp[@]} )); then
    target_cert_dirs+=( ${tmp[*]} )
    (( $DEBUG )) && debug "App Portal found!"
else
    warn "No App Portal found!"
fi

mapfile -t tmp <<< $(find ${syno_cert_dir}/ReverseProxy -mindepth 2 -maxdepth 2 -type d 2>/dev/null)
if (( ${#tmp[@]} )); then
    target_cert_dirs+=( ${tmp[*]} )
    (( $DEBUG )) && debug "Reverse Proxy found!"
else
    warn "No Reverse Proxy found!"
fi

mapfile -t tmp <<< $(find /usr/local/etc/certificate -mindepth 2 -maxdepth 2 -type d 2>/dev/null)
if (( ${#tmp[@]} )); then
    target_cert_dirs+=( ${tmp[*]} )
        oIFS=$IFS
        IFS=$'\n'
        packages_to_restart=( `for path in ${tmp[@]}; do echo $path | awk -F/ '{print $6}'; done | sort -du`)
        IFS=$oIFS
    (( $DEBUG )) && debug "Packages found!"
else
    warn "No Package found!"
fi

if (( $DEBUG )); then
  echo "--- ${target_cert_dirs[@]} ---"
  set -x
else
  mv /tmp/{privkey,fullchain,cert}.pem "${certs_src_dir}/" 2>/dev/null || error_exit "Halting because of error moving files"
  chown root:root "${certs_src_dir}/"{privkey,fullchain,cert}.pem || error_exit "Halting because of error chowning files"
fi

info "Certs moved from /tmp & chowned."
if ! (( $DEBUG )); then
  for target_dir in "${target_cert_dirs[@]}"; do
    info "Copying certificates to '$target_dir'"
    if ! cp "${certs_src_dir}/"{privkey,fullchain,cert}.pem "$target_dir/" && \
        chown root:root "$target_dir/"{privkey,fullchain,cert}.pem; then
      warn "Error copying or chowning certs to ${target_dir}"
    fi
  done
fi

info "Rebooting all the things..."
if ! (( $DEBUG )); then
  for svc in "${services_to_restart[@]}"; do
    /usr/syno/bin/synosystemctl restart "$svc"
  done
  for pkg in "${packages_to_restart[@]}"; do
    /usr/syno/bin/synopkg is_onoff "$pkg" 1>/dev/null && /usr/syno/bin/synopkg restart "$pkg"
  done

  if ! /usr/syno/bin/synow3tool --gen-all && sudo systemctl reload nginx; then
    warn "nginx failed to restart"
  fi
fi

info "Completed"

Chú thích

  • Nếu DEBUG=1, script không chép SSL certificate cho các dịch vụ cần thiết mà chỉ liệt kê các thư mục cần cập nhật SSL
  • Mặt khác, có thể export Synology SSL certificate để dùng cho máy khác thro cách tương tự

Comments Off on Syno NAS: sao chép wildcard SSL

Filed under Software

Comments are closed.