NextCloud на Raspberry Pi /Arch Linux ARM/: налаштування https, ssl та динамічного DNS, налаштування домену [ч. 2]

Продовжуємо встановлення та налаштування власного хмарного файлобмінника (і не тільки) для забезпечення віддаленого доступу

В першій частині ми розглядали як встановити Nextcloud на Raspberry Pi (RPi).

Nextcloud працюватиме лише в локальній мережі, де знаходиться RPi. Для забезпечення роботи через інтернет, в тому числі для роботи/підключення на мобільних пристроях, а також для забезпечення безпеки, необхідно налаштувати HTTPS та згенерувати ключі SSL.

Також, оскільки RPi стане доступним в інеті важливо забезпечити його роботу як сервера. Для цього як мінімум встановити Fail2Ban, налаштувати файєрвол, змінити правила доступу по SSH (наприклад, змінити порт з 22 на 3456).

Динамічний DNS використовується у випадку, якщо відсутній зовнішній/білий IP. Як правило, в домашніх мережах т.зв. сірий/динамічний IP, який періодично змінюється. Тому необхідно використовувати сервіси для оновлення IP і прив'язування його до певного домену.

Також нам потрібен домен (домене ім'я) для організації доступу в Nextcloud. Можна обійтись без доменого імені, використовуючи сервіси на зразок No-IP, але в даній статі розглядається випадок з використанням власного домену та сервісу Cloudflare.

Вся процедура здійснюється на Raspberry Pi, на якому встановлено Arch Linux ARM.

Кроки/дії по налаштуванню HTTPS

  • встановити ddclient на распері

    sudo pacman -S ddclient
    
  • зробити резервну копію файлу конфігурації ddclient

    sudo cp /etc/ddclient/ddclient.conf /etc/ddclient/ddclient.conf.bak
    
  • відкрити файл /etc/ddclient/ddclient.conf, вилучити всі дані та вставити наступні налаштування, зберегти та закрити файл

    daemon=1000
    use=web, web=checkip.dyndns.com/, web-skip='IP Address'
    pid=/var/run/ddclient.pid
    ssl=yes
    

    параметри daemon та pid важливо встановити для платформи Arch Linux (див. тут і тут)

  • налаштовуємо Cloudflare (платформа, за допомогою якої зможемо оновлювати динамічний IP)

    • зареєструватись на сайті Cloudflare

      • додати свій домен в особистому кабінеті (домен можна придбати безпосередньо в Cloudflare або на іншому ресурсі; є сервіс freenom.tk, де можна отримати безкоштовний домен на 1 рік)
      • змінити налаштування nameservers згідно інструкцій Cloudflare
    • отримати API ключ в Cloudflare: зайти в розділ "Мій профіль" (My profile), вкладка API tokens, скопіювати Global API key (нажати кнопку 'view' для перегляду ключа)

    • у меню SSL/TLS, вкладка Overview вибрати 'Full' для методу шифрування (Your SSL/TLS encryption mode)

      Можна вибрати метод 'Flexible', але тоді у файлі налаштувань Nginx (див. внизу) потрібно замість return 302 https://$server_name:443$request_uri; вказати

      if ($http_x_forwarded_proto = "http") {
          return 301 https://$server_name$request_uri;
      }
      

      Деталі про цю проблему див. тут.

  • внести такі доповнення до файлу /etc/ddclient/ddclient.conf (логін - свій емейл, пароль - API ключ, який раніше скопіювали, зона - зареєстрований домен, внизу під зоною - або субдомен, або домен; субдомен повинен бути зареєстрованим в DNS Cloudflare)

    protocol=cloudflare
    server=www.cloudflare.com
    login=your_email
    password=your_api-key
    zone=your_domain.com
    anything.your_domain.com
    
  • перезапустити ddclient

    sudo systemctl restart ddclient
    
  • створити SSL сертифікати (повний опис тут)

    • генеруємо приватний ключ та сертифікат

      sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt
      

    В процесі заповнити інформацію (відповіді на питання)

      ``` bash
      Country Name (2 letter code) [AU]:US
      State or Province Name (full name) [Some-State]:New York
      Locality Name (eg, city) []:New York City
      Organization Name (eg, company) [Internet Widgits Pty Ltd]:Bouncy Castles, Inc.
      Organizational Unit Name (eg, section) []:Ministry of Water Slides
      Common Name (e.g. server FQDN or YOUR name) []:server_IP_address
      Email Address []:admin@your_domain.com
      ```
      В Common Name важливо зазначити свій домен або IP адресу серверу
    
    • згенерувати групу криптографічного захисту (це займе досить тривалий час, потрібно набратись терпіння)

      sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
      
  • налаштувати Nginx для використання SSL сертифікатів

    • створюємо конфігураційні файли

      Створюємо файл self-signed.conf

      sudo mkdir /etc/nginx/snippets
      sudo vim /etc/nginx/snippets/self-signed.conf
      

      Додати в цей файл такі налаштування:

      ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
      ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
      

      зберігаємо і закриваємо файл.

      Створюємо інший файл - ssl-params.conf

      sudo vim /etc/nginx/snippets/ssl-params.conf
      

      і вставити налаштування:

      # from https://cipherli.st/
      # and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
      
      ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
      ssl_prefer_server_ciphers on;
      ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
      ssl_ecdh_curve secp384r1;
      ssl_session_cache shared:SSL:10m;
      ssl_session_tickets off;
      ssl_stapling on;
      ssl_stapling_verify on;
      resolver 9.9.9.9 1.1.1.1 valid=300s;
      resolver_timeout 5s;
      # Disable preloading HSTS for now.  You can use the commented out header line that includes
      # the "preload" directive if you understand the implications.
      #add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
      add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
      
      ssl_dhparam /etc/ssl/certs/dhparam.pem;
      
    • налаштовуємо конфігураційні файли Nginx для використання SSL (взяті налаштування звідси і звідси)

      sudo vim /etc/nginx/sites-available/nextcloud.conf	
      

      змінюємо файл на:

      upstream php-handler {
              server unix:/run/php-fpm/php-fpm.sock;
      }
      
      server {
          listen 80;
          listen [::]:80;
          server_name your.domain.tld;
              # enforce https
              return 302 https://$server_name:443$request_uri;
      }
      
      server {
              listen 443 ssl http2;
              listen [::]:443 ssl http2;
              server_name your.domain.tld;
      
          include snippets/self-signed.conf;
          include snippets/ssl-params.conf;
      
              add_header Referrer-Policy "no-referrer" always;
              add_header X-Content-Type-Options "nosniff" always;
              add_header X-Download-Options "noopen" always;
              add_header X-Frame-Options "SAMEORIGIN" always;
              add_header X-Permitted-Cross-Domain-Policies "none" always;
              add_header X-Robots-Tag "none" always;
              add_header X-XSS-Protection "1; mode=block" always;
      
              # Remove X-Powered-By, which is an information leak
              fastcgi_hide_header X-Powered-By;
      
              # Path to the root of your installation
              root /usr/share/webapps/nextcloud/;
      
              # set max upload size
              client_max_body_size 512M;
              fastcgi_buffers 64 4K;
      
              # Enable gzip but do not remove ETag headers
              gzip on;
              gzip_vary on;
              gzip_comp_level 4;
              gzip_min_length 256;
              gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
              gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
      
              location / {
                  rewrite ^ /index.php$request_uri;
              }
      
              location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
                  deny all;
              }
              location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) {
                  deny all;
              }
      
              location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+)\.php(?:$|\/) {
                  fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
                  include fastcgi_params;
                  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                  fastcgi_param PATH_INFO $fastcgi_path_info;
                  #fastcgi_param HTTPS on;
                  #Avoid sending the security headers twice
                  fastcgi_param modHeadersAvailable true;
                  fastcgi_param front_controller_active true;
                  fastcgi_pass php-handler;
                  fastcgi_intercept_errors on;
                  fastcgi_request_buffering off;
              }
      
              location ~ ^\/(?:updater|ocs-provider)(?:$|\/) {
                  try_files $uri/ =404;
                  index index.php;
              }
      
              # Adding the cache control header for js, css and map files
              # Make sure it is BELOW the PHP block
              location ~ \.(?:css|js|woff2?|svg|gif|map)$ {
                  try_files $uri /index.php$request_uri;
                  add_header Cache-Control "public, max-age=15778463";
                  # Add headers to serve security related headers (It is intended to
                  # have those duplicated to the ones above)
                  # Before enabling Strict-Transport-Security headers please read into
                  # this topic first.
                  # add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
                  #
                  # WARNING: Only add the preload option once you read about
                  # the consequences in https://hstspreload.org/. This option
                  # will add the domain to a hardcoded list that is shipped
                  # in all major browsers and getting removed from this list
                  # could take several months.
                  add_header X-Content-Type-Options nosniff;
                  add_header X-XSS-Protection "1; mode=block";
                  add_header X-Robots-Tag none;
                  add_header X-Download-Options noopen;
                  add_header X-Permitted-Cross-Domain-Policies none;
                  add_header Referrer-Policy no-referrer;
      
                  # Optional: Don't log access to assets
                  access_log off;
              }
      
              location ~ \.(?:png|html|ttf|ico|jpg|jpeg)$ {
                  try_files $uri /index.php$request_uri;
                  # Optional: Don't log access to other assets
                  access_log off;
              }
            }
      
  • перевіряємо налаштування nginx

    sudo nginx -t
    

    Повинно з'явитись таке повідомлення:

    Output
    nginx: [warn] "ssl_stapling" ignored, issuer certificate not found
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
    

    Це означає, що налаштування вірні

  • перезапускаємо nginx

    sudo systemctl restart nginx
    
  • перекинути порти на роутері (port forwarding)

    Перекидання портів необхідне для того, щоб RPi (сервер) із встановленим Nextcloud був доступним для/з 'інтернету'. Оскільки запити HTTP надходитимуть на роутер на порт 80 або 443, роутеру необхідно вказати куди перенапрвляти такі запити (по протоколу TCP).

    Як правило на роутерах перекидання порт здійснюється в меню 'Безпекаʼ, розділі ʼТрансляція мережевих адрес'. Для цього потрібно створити нове правило (точніше 2), в яких вказати:

    Назва/Опис: ...
    Інтерфейс: наприклад, назва з'єднання з провайдером
    Протокол: TCP
    Порт: 80 і 443
    Перенаправити на: адреса хоста/сервера/Raspberry Pi (наприклад, 192.168.1.2)
    Порт перенаправлення: 80 і 443
    
  • заходимо в браузері на свій домен і повинна відкритись сторінка Nextcloud для логіну

    Вводимо логін і пароль і чекаємо на запуск системи.

Звернути увагу

Якщо ваш провайдер (ISP) використовує технологію CGNAT (Carrier-grade Network Address Transfer), то використання динамічного DNS не працюватиме. Це пов'язано з тим, що вам надається два IP - один при взаємодії із провайдером, інший - той, яким "бачить" вас інтернет, тобто зовнішній. Відповідно динамічний DNS не працюватиме, оскільки визначить зовнішній IP. Але при зверненні до такого IP запит надходитеме не на ваш роутер, а до провайдера. Вирішення цієї проблеми або звернутись до провайдера, щоб він здійснював перенаправлення портів (але це малоймовірно), або придбавати білий зовнішній IP. В останньому випадку вже не потрібно налаштовувати динамічний DNS, достатньо лише в сервісі Cloudflare для свого домену вказати запис 'A' і зазначити свій білий IP.



Вся ця інструкція склалась в процесі налаштування на своєму RPi протоколу HTTPS і завдяки ВіКі ArchLinux, Nextcloud, статтям з Digital Ocean, а також на інструкціях pimylifeup.com: 1 і 2.


ч. 1: Встановлення NextCloud на Raspberry Pi під управлінням Arch Linux ARM