Day After Day
tsurezure naru mamani...
ANOTHER DECADE

from 2021 when it's begining after/with CORONA Virus.

簡易WEBサーバを作ってみた

10月
19
2025
Back
Alt+HOME


一応公開目的なので最低限のセキュリティ対策をしておこうと、HTTPS化の練習をこの前行ったので、トータルでその他注意点も含めてレシピ化しておこうと思う。


使用する機器・アプリは、Raspberry Pi に Pi-OS trixie 64bit を入れ、WEB サーバとして Apache2 + PHP。 なお、MyApp と言う Python アプリケーションを /opt 以下にインストールし、Python の仮想環境で動かし、 その出力を html ファイルとして Document Root に配布するものとする。

なお、SSL/TLS認証用には Certbot を利用、ファイアウォールには nftables を新たにインストールして使用する。

又、URLとしてダイナミックDNSを dynamicdns.net (仮) とする。

SSL/TSL化したWEBの入れ物を作る


    詳しくはWEBサーバを HTTPS 化するを参照

  1. ポートを変更する前に、標準設定の 80 ポートで certbot に依る SSL/TLS環境を作る

  2. $ sudo apt install php   # phpをインストールするとapache2もインストールされDocument Rootにテスト用phpが配置される。
    $ sudo apt install certbot python3-certbot-apche -y
    $ sudo sertbot --apache -d dynamicdns.net
            
    いずれポートを変更した後は、他のポート80の PC から更新された証明書を転送する仕組みを作る。(上記リンク参照)

  3. SSL/TLS の環境設定ファイルに、取得した証明書の有る場所を指定して Apache を再構築する

  4. $ sudo nano /etc/apache2/sites-available/ssl-8080.conf
      GNU nano 8.4                          /etc/apache2/sites-available/ssl-8080.conf
    <VirtualHost *:8080>
        ServerName dynamicdns.net
        DocumentRoot /var/www/html-8080     # 通常デフォルトは /var/www/html となるので後にフォルダ作成
    
        SSLEngine on
        SSLCertificateFile /etc/letsencrypt/live/dynamicdns.net/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/dynamicdns.net/privkey.pem
    
        <Directory /var/www/html-8080>
            Options Indexes FollowSymLinks
            AllowOverride All
            Require all granted
        </Directory>
    
        ErrorLog ${APACHE_LOG_DIR}/ssl-8080-error.log
        CustomLog ${APACHE_LOG_DIR}/ssl-8080-access.log combined
    </VirtualHost>
    $ sudo a2ensite ssl_8080.conf
    $ sudo apache2ctl configtest
    AH00526: Syntax error on line 5 of /etc/apache2/sites-enabled/ssl_8090_tm-listen.conf:
    Invalid command 'SSLEngine', perhaps misspelled or defined by a module not included in the server configuration
    このエラーが出たら SSL が起動していない可能性が有る。その場合は・・

    $ sudo a2enmod ssl
    なお、apache2.confに ServerName の指定が無い場合もエラーになる。apache2.conf に指定してからテストする。

    $ sudo nano /etc/apache2/apache2.conf
      GNU nano 8.4                          /etc/apache2/apache2.conf
            :    (追記)
            :
    ServerName dynamicdns.net

    $ sudo apache2ctl configtest
    Syntax OK
    
    $ sudo systemctl restart apache2.service

  5. 先ず条件として、Apache2 を使用して、ポートを 443 ではなく 8080 にするという設定で開始する。 そのために前述の ssl-8080.conf のフォルダ指定にも /var/www/html-8080 と記述した。

  6. $ sudo nano /etc/apache2/ports.conf
      GNU nano 8.4                          /etc/apache2/ports.conf
    Listen 8080
    
    <IfModule ssl_module>
        Listen 443
    </IfModule>
    
    <IfModule mod_gnutls.c>
        Listen 443
    </IfModule>

  7. WEB サーバのドキュメント用フォルダを専用ユーザで新規作成

  8. 標準的には /var/www/html がインストール時 root 権限で作成されている。

    $ sudo useradd -r -s /usr/sbin/nologin myapp     # 以後 MyApp 関連にアクセスするユーザ
    $ sudo mkdir /var/www/html-8080
    $ sudo chown -R myapp:myapp /var/www/html-8080
    $ sudo chmod -R 755 /var/www/html-8080
    $ ls /var/www
    html  html-8090
    

アプリケーションの格納場所と起動方法


  1. 先ずは格納場所と Python の安全な起動に関する処置 (専用ユーザ:myapp)

  2. $ sudo mkdir -p /opt/MyApp
    $ sudo chown -R myapp:myapp /opt/MyApp
    $ sudo chmod -R 750 /opt/MyApp
    $ sudo -u myapp python3 -m venv /opt/MyApp/.venv        # Python 仮想環境の作成。隠しフォルダでなくても良い
    $ sudo -u myapp /opt/MyApp/.venv/bin/pip install --no-cache-dir requests
    $ sudo -u myapp /opt/MyApp/.venv/bin/pip install --no-cache-dir beautifulsoup4
    仮想環境にインストールされた pip を使って必要なライブラリーをインストールする。

    $ sudo -u myapp /opt/MyApp/.venv/bin/python /opt/MyApp/MyApp.py

  3. アプリの自動起動を設定する

  4. $ sudo nano /etc/systemd/system/MyApp.service
      GNU nano 8.4                          /etc/systemd/system/MyApp.service
    [Unit]
    Description=MyApp Python Service
    After=network.target
    
    [Service]
    User=myapp
    Group=myapp
    WorkingDirectory=/opt/MyApp
    ExecStart=/opt/MyApp/.venv/bin/python /opt/MyApp/MyApp.py
    Restart=always
    RestartSec=5
    StandardOutput=journal
    StandardError=journal
    
    [Install]
    WantedBy=multi-user.target

  5. Pythonアプリの html 出力と Apache2 の DocumentRoot との関係

  6.   GNU nano 8.4                          /opt/MyApp/MyApp.py
        """
            :
            # html構成
            :
        """
            :
        # ローカルへ保存
        with open("/var/www/html-8080/MyApp.html", "w", encoding="utf-8") as f:
            f.write(html)        
            :
    ユーザ(myapp)権限で動いている MyApp の出力が ユーザ(myapp)所有の /var/www/html-8080 に書き込まれる。
    このようにアプリケーションごとにフォルダやポート管理が可能となる。

SSL/TLS ポートと SSH ポートのみを通すファイアウォールを構築する


  1. nftablesをインストール

  2. $ sudo apt install nftables

  3. nftables の設定ファイルを編集

  4. $ sudo nano /etc/nftables.conf
      GNU nano 8.4                          /etc/nftables.conf
    #!/usr/sbin/nft -f
    
    flush ruleset
    
    table inet filter {
        chain input {
            type filter hook input priority filter;
            policy drop;
    
            iif lo accept
            ct state established,related accept
            tcp dport 22 accept
            tcp dport 8080 accept
        }
    
        chain forward {
            type filter hook forward priority filter;
            policy drop;
        }
    
        chain output {
            type filter hook output priority filter;
            policy accept;      # ここは標準では drop になっている (SSHがいきなり切れる)
        }
    }

  5. 起動とその他関連コマンド

  6. $ sudo systemctl enable nftables
    $ sudo systemctl start nftables
    
    $ sudo nft list ruleset                     # nftables.conf の内容を表示
    $ sudo nft list chain inet filter input     # 特定チェインの確認
    $ sudo ss -tlnp                             # サービスの Listen ポート
    
    


Back
Alt+HOME