20200917のLinuxに関する記事は7件です。

Raspberry PiでApache2.4+PHP7.4をソースコンパイルしてWebサーバー構築 - 3.MySQLを使う

前提と準備

Linuxサーバー構築の記事

前回はApache2.4にPHP7.4をソースコンパイルでWebアプリ環境を構築しましたが、残念なことに、標準でRaspberry Pi向けのLinuxは、MySQLをサポートしておらず、RPMやAPTのリポジトリにも存在しません。ですが、外部MySQLサーバーを接続することは可能です。

簡単なためにWebサーバーと一体でデータベースのMySQLを構築したいと思っても、Raspberry Piの場合はそうにはいかず、たとえインストールできたとしても、microSDの書き込みには非常に不向きなので、今後ラズパイがM.2 SSD相当のストレージに対応しているラインアップを展開すれば、MySQLのサポートも可能かもしれないですが…(✿・ω・)それまではとにかくMySQLを無理にラズパイに導入してストレージにエラーが出ても、またもや本末転倒だしなぁ…

環境

  • Webサーバープログラム:Apache 2.4.46 + PHP 7.4.10
  • クライアント:Windows10 Pro
  • サーバーのアーキテクチャ:Raspberry Pi 3B+(armv8搭載) Linuxのディストリビューション:openSUSE 15.1 Leap(64bit) / Raspberry Pi OS 2020.08版(32bit)
  • 別途用意する端末:MySQLサーバー(私の場合はCentOS 8.1にMySQL 8.0を構築しました)

前提

  • ユーザーはrootでインストール(私の検証ではadminという管理者アカウントにて、そこからsudoで処理しています)
  • openSUSEではファイアウォールはfirewalldを使う(ディストリビューション独自のファイアウォールコマンドは使用しない)。ラズパイのRaspberry Pi OSでは、firewalldについて、IPv6周りの連動が糞だったので、Debian系標準のufwを使用することにしました。
  • 前回の記事のApache+PHP導入を完了していること

サーバー条件

IPアドレス

  • クライアント:192.168.1.11
  • Webサーバー:192.168.1.22 (前回まで192.168.1.18でしたが、DBで使われていたので、ラズパイのIPアドレスを変更しました)
  • データベースサーバー:192.168.1.18 (ラズパイで使ってたのと重複していたので、ラズパイの方を192.168.1.22に変更しました)
  • 所属ネットワークセグメント:192.168.1.0/24 Webサーバー+MySQL

パッケージを個別ダウンロードしてインストールする機能とバージョン(2020年6月時点)

  • zlib-1.2.11.tar.gz
  • apr-1.7.0.tar.gz
  • apr-util-1.6.1.tar.gz
  • httpd-2.4.46.tar.gz
  • php-7.4.10.tar.gz

それ以外の必要なパッケージは、ディストリビューションの標準パッケージコマンド(dnfやaptなど)でインストールし、個別ダウンロードは不要です。

ダウンロードについては、公式サイトにアクセスして、そこからダウンロードしてFTPで転送するか、ダウンロードファイルのURLさえわかれば、wgetで入手することもできますが、入手方法は省略しています。

作業手順

MySQLクライアントの導入

MariaDBクライアントツールのインストール

MySQLコマンドを管理するクライアントに、「MySQL」と明確なパッケージは、ラズパイ向けLinuxには含まれていないため、MariaDBクライアントをインストールしました。

openSUSE15.1(RaspberryPi)
# zypper -n install mariadb-client
RaspberryPiOS(2020.08)
# apt-get -y install mariadb-client

これで、MySQLコマンドがラズパイから使えるようになりました。

MySQLサーバーでの準備

サーバーでのユーザーとデータベース

今回は、CentOS 8.1にMySQLサーバーを構築した仮想マシンを使うので、この記事で構築したデータベースを使ってみます

  • データベース名:manutest
  • テストユーザー名:test
  • テストユーザーパスワード:test1
  • 文字コード:UTF-8
  • MySQLサーバーのIPアドレス:192.168.1.18

なおパスワードは私的都合で「test0」から「test1」に変えました。

MySQLサーバー上での準備

最初にMySQLが他の端末からアクセスできるように、MySQLサーバーでいろいろ準備します。

MySQLのrootでログインします。

MySQLサーバー(CentOS8.1)
[このコマンドに限り、MySQLサーバー上で実施するものです]
# mysql -u root -p
Enter password:  ← MySQLのrootパスワードを入力

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| manutest           |  ← 作成したデータベースが表示される
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

mysql> CREATE USER 'test'@'192.168.1.22' IDENTIFIED BY 'test1';
↑ ラズパイのIPアドレス「192.168.1.22」向けのユーザー名「test」を作成する

mysql> GRANT ALL ON manutest.* TO 'test'@'192.168.1.22';
↑ データベース「manutest」に対して「test」が「192.168.1.22」から全機能を使える

エラーがなく「Query OK, 0 rows affected」が表示されれば、データベースとユーザーは作成完了。

つまり、MySQLとApacheが同一のサーバーマシンにある場合は「localhost」で済んだが、今回はラズパイ→MySQLサーバーからという、他のサーバーにアクセスするので、以下のように、ユーザー名+@マーク+ホスト、というように、

CREATE USER '<ユーザー名>'@'<ラズパイのホスト>' IDENTIFIED BY '<パスワード>';
GRANT ALL ON <データベース名>.* TO '<ユーザー名>'@'<ラズパイのホスト>';

というような指定が必要だということですね(˶ ・ᴗ・ )੭

MySQLサーバーでは、CentOSでfirewalldの開放も必要でしたね(˶ ・ᴗ・ )੭**

MySQLサーバー(CentOS8.1)
[このコマンドに限り、MySQLサーバー上で実施するものです]
# firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="3306" protocol="tcp" accept'
# firewall-cmd --reload

MySQLのポートは3306/TCPなので、そのポートを開放することで、MySQLサーバーにPHPなんかがアクセスできるということ…

Raspberry Pi→MySQLサーバーに接続できるか確認

MySQLサーバーでの作業はここまで。
では、Raspberry Piに戻って、MySQLを使えるか試します。mysqlコマンドで「-h」オプションでホストを指定できます

RaspberryPi(ラズパイOS・openSUSE15.1)
# mysql -h 192.168.1.18 -u test -p
Enter password:  ← パスワード「test1」を入れる
(中略)

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| manutest           |  ← 作成したデータベースが表示されれば成功
+--------------------+
2 rows in set (0.00 sec)

ラズパイ→DBサーバー接続成功!!

ちゃんとテーブルの中身も参照できるまでに至りました!!( ˶˙ᵕ˙˶ )

PHPからMySQLサーバーを使う

PHPからMySQLの接続を確認

MySQLサーバーには、前回仮想マシンのCentOSで構築したように、テスト用テーブルを使ってみます。

テーブル名:testtb

id name memo
INT VARCHAR(64) VARCHAR(256)
必須属性 PRIMARY KEY NOT NULL 初期値NULL
その他属性 AUTO_INCREMENT - -

まずはテーブルを使う前に、PHPでMySQLに接続できるかちゃんと確かめないといけません(*˘ᗜ˘*;)

接続確認ページを作ります

# cd ~
# vi connect.php
connect.php
<?php
    $dsn = 'mysql:dbname=manutest; host=192.168.1.18';
    $usr = 'test';
    $pass = 'test1';

    try {
        $db = new PDO($dsn, $usr, $pass);
        print 'Connection successful.';
        $db = NULL;
    }
    catch(PDOException $e){
        die('Connect error : '.$e->getMessage());
    }
?>

これを、Apache導入時にインストールした先のWebページの格納場所 /usr/local/apache2/htdocs/に移動します。

# mv connect.php /usr/local/apache2/htdocs/

PHPページの配置なので、特にApacheを再起動することは不要なので、https://[LinuxサーバーのIPアドレス]/connect.php と入力して確認。192.168.1.18はMySQLサーバーで使われていて、ラズパイLinuxサーバーのIPアドレスは192.168.1.22なので、ブラウザでhttps:~の後に、192.168.1.22/connect.phpをURLを入力してアクセス。

ラズパイ上のPHP→DBサーバー接続
やっと成功した!!⑅︎◡̈︎*

PHPからMySQLにデータを登録できるかを確認

続いて、いよいよデータが登録できるかを確認します。
再びWebページを作ります。

まずは登録フォームから。

# vi test_form.html
test_form.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>テストページ - Test page</title>
</head>
<body>
<form method="POST" action="test_form.php">
    <input type="text" name="name" />
    <input type="text" name="memo" />
    <input type="submit" value="Submit" />
</form>
</body>
</html>

続いて、フォームから受け取ったデータをMySQLデータベースへ追加するPHPを作成

# vi test_form.php
test_form.php
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>テスト入力 - Test insert</title>
</head>
<body>
<?php
    function getDb(){
        $dsn = 'mysql:dbname=manutest; host=192.168.1.18';
        $usr = 'test';
        $pass = 'test1';

        try {
            $db = new PDO($dsn, $usr, $pass);
            $db->exec('SET NAMES utf8');
        }
        catch(PDOException $e){
            die('Connect error : '.$e->getMessage());
        }

        return $db;
    }

    try {
        $db = getDb();

        $stt = $db->prepare('INSERT INTO testtb (name, memo) VALUES (:one, :two)');

        $stt->bindValue(':one', $_POST['name']);
        $stt->bindValue(':two', $_POST['memo']);
        $stt->execute();

        print $_POST['name'].' - '.$_POST['memo'].' : Insert OK.';

        $stt = $db->query("SELECT * FROM testtb");
?>
    <table border="1">
<?php
        while($row = $stt->fetch(PDO::FETCH_ASSOC)){
?>
        <tr>
            <td><?php print $row['name']; ?></td>
            <td><?php print $row['memo']; ?></td>
        </tr>
<?php
        }
?>
   </table>
<?php
         $db = NULL;
   }
    catch(PDOException $e){
        die('Process error : '.$e->getMesssage());
    }
?>
</body>
</html>

上記2ファイルをApacheのWebページデータの場所へ。

# mv test_form.* /usr/local/apache2/htdocs/

では、ブラウザでhttps://[IPアドレス]/test_form.htmlにアクセスして、データを登録してみると…

ラズパイPHP→DBサーバー操作

これも登録成功しました!(˶ ・ᴗ・ )੭⚐⚑
PCより非力かつストレージもmicroSDというDBの読み書きに不向きなラズパイだからこそ、外部のDB用のサーバーと一緒に外部アクセスすることで、ラズパイもDBを扱えることが実感できた瞬間です

あとがき

Raspberry PiはPCと比べて非力でストレージもmicroSDなので、PCと全く同じようなサーバー構築だと、メモリ不足やデータベースの非対応やらで比較的道のりは険しい一方で、省電力という恩恵ならではのメリットもまたあるということを、今回の構築を通して感銘したな…とも思う(♥´꒳`*)

今後と次回

PHPによるWebアプリサーバー構築のほかにも、Java(OpenJDK)によるWebアプリサーバーについても、構築に触れてみたい

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Raspberry PiでApache2.4+PHP7.4をソースコンパイルしてWebサーバー構築 - 2.PHP導入編

前提と準備

Linuxサーバー構築の記事

前回はApache httpd 2.4.46をソースコンパイルでRaspberry Piに構築しましたが、今回は、前回に引き続き、ApacheにWebアプリサーバーの基幹であるPHP 7.4をソースコンパイルで導入します(⑅•ᴗ•⑅)

環境

  • Webサーバープログラム:Apache 2.4.46 + PHP 7.4.10(ソースコンパイル)
  • クライアント:Windows10 Pro
  • サーバーのアーキテクチャ:Raspberry Pi 3B+(armv8搭載) Linuxのディストリビューション:openSUSE 15.1 Leap(64bit) / Raspberry Pi OS 2020.08版(32bit)

前提

  • ユーザーはrootでインストール(私の検証ではadminという管理者アカウントにて、そこからsudoで処理しています)
  • openSUSEではファイアウォールはfirewalldを使う(ディストリビューション独自のファイアウォールコマンドは使用しない)。ラズパイのRaspberry Pi OSでは、firewalldについて、IPv6周りの連動が糞だったので、Debian系標準のufwを使用することにしました。
  • 前回の記事のApache導入を完了していること(動作が確認できて、Webサーバーとして構築されていること)

サーバー条件

IPアドレス

  • クライアント:192.168.1.11
  • Webサーバー:192.168.1.18(どのディストリビューションでも同じIPアドレスで検証)
  • 所属ネットワークセグメント:192.168.1.0/24 Webサーバー.png

パッケージを個別ダウンロードしてインストールする機能とバージョン(2020年6月時点)

  • zlib-1.2.11.tar.gz
  • apr-1.7.0.tar.gz
  • apr-util-1.6.1.tar.gz
  • httpd-2.4.46.tar.gz
  • php-7.4.10.tar.gz

それ以外の必要なパッケージは、ディストリビューションの標準パッケージコマンド(dnfやaptなど)でインストールし、個別ダウンロードは不要です。

ダウンロードについては、公式サイトにアクセスして、そこからダウンロードしてFTPで転送するか、ダウンロードファイルのURLさえわかれば、wgetで入手することもできますが、入手方法は省略しています。

作業手順

PHPのインストール

PHPのソースコンパイルに必要なライブラリを導入

openSUSE15.1(RaspberryPi)
# zypper -n install libxml2-tools libxml2-devel sqlite3-devel oniguruma-devel
RaspberryPiOS(2020.08)
# apt-get -y install libxml2 libxml2-dev libsqlite3-dev libonig-dev

PHP7.3までは、SQLiteと鬼車のライブラリを使わなくてもマルチバイト文字列を扱うようインストールができたのですが、PHP7.4ではソースコンパイルで必須となりました。

PHPのソースコンパイル(実際swap仮想メモリ不足で強制終了しハマった)

コンパイルには30~40分前後かかる見込みです。Apacheより規模が大きいので、コンパイル中はコーヒー1杯で休憩をはさんだほうがいいかもしれません(*˘︶˘*).。.:*♡

# cd [php-7.4.10.tar.gzが置いてあるディレクトリ]
# tar xvzf php-7.4.10.tar.gz
# cd php-7.4.10/
# ./configure --with-apxs2=/usr/local/apache2/bin/apxs --with-mysqli --with-pdo-mysql --enable-mbregex --enable-mbstring
# make
# make test
  • MySQLはPDOを有効にします
  • マルチバイト文字列を有効にします

「make」「make test」が時間がかかるコマンドです。
途中でエラーがなければコンパイル完了ですが、そこでRaspberry Pi OSのほうで問題発生。

RaspberryPiOS(2020.08)
# make

/bin/bash /home/admin/php-7.4.10/libtool --silent --preserve-dup-deps --mode=compile cc -I/home/admin/php-7.4.10/ext/fileinfo/libmagic -Iext/fileinfo/ -I/home/admin/php-7.4.10/ext/fileinfo/ -DPHP_ATOM_INC -I/home/admin/php-7.4.10/include -I/home/admin/php-7.4.10/main -I/home/admin/php-7.4.10 -I/home/admin/php-7.4.10/ext/date/lib -I/usr/include/libxml2 -I/home/admin/php-7.4.10/ext/mbstring/libmbfl -I/home/admin/php-7.4.10/ext/mbstring/libmbfl/mbfl -I/usr/local/include -I/home/admin/php-7.4.10/TSRM -I/home/admin/php-7.4.10/Zend  -D_REENTRANT -pthread  -I/usr/include -g -O2 -fvisibility=hidden -pthread -Wall -Wno-strict-aliasing -DZTS -DZEND_SIGNALS   -c /home/admin/php-7.4.10/ext/fileinfo/libmagic/apprentice.c -o ext/fileinfo/libmagic/apprentice.lo
cc: fatal error: 強制終了 signal terminated program cc1
compilation terminated.
make: *** [Makefile:738: ext/fileinfo/libmagic/apprentice.lo] エラー 1

こんなふうにmake中で強制終了してしまった(´•ω•̥`)
PHPは相当の処理の多さでビルドするので、Raspberry Pi OSだけなぜ…と思いつつ、メモリの空き容量を調べてみたら…

RaspberryPiOS(2020.08)
# free
              total        used        free      shared  buff/cache   available
Mem:         948072      389256      367752       99504      191064      394740
Swap:        102396      102256         140

Raspberry Pi OSではたったの100MBしかswap領域がなかったことに気が付いて、空きが1MBだけ…(openSUSEはRaspberry Piでも400MBはあった)

なので、swap領域を増やして仮想メモリを増やすことにした。Raspberry Pi OSでは、swapはパーテーションではなくdphys-swapfileで定義される

RaspberryPiOS(2020.08)
# vi /etc/dphys-swapfile
CONF_SWAPSIZE=100       ← 増量する
CONF_SWAPFACTOR=2       ← 倍率を設定する

# reboot

私の場合は200MBに増量して、倍率を2に設定しました。
再起動して再ビルドし、今度こそうまく成功しました!!
【でも実際は再起動したことによってビルドがうまくいったっぽい】

しかしさらなる問題が発生した
今度は「make test」でSegmentation Faultとなってしまう事象が発生している。ビルドは成功したはずなのに、テストがセグメンテーション違反(Windowsでいうアプリケーションエラーと呼ばれている)でクラッシュする事象が発生。。。

テストツールに問題があるのか、ビルドしたモジュールに問題があるのか、今回のところはとりあえずPHPを動かして調べてみることにするので、テストはいったん保留。

PHPのインストール

コンパイルが完了したら、インストールします。

# make install
Installing PHP SAPI module:       apache2handler
/usr/local/apache2/build/instdso.sh SH_LIBTOOL='/opt/apr-1.7.0/build-1/libtool' libphp7.la /usr/local/apache2/modules
/opt/apr-1.7.0/build-1/libtool --mode=install install libphp7.la /usr/local/apache2/modules/
libtool: install: install .libs/libphp7.so /usr/local/apache2/modules/libphp7.so
libtool: install: install .libs/libphp7.lai /usr/local/apache2/modules/libphp7.la
libtool: warning: remember to run 'libtool --finish /home/admin/php-7.4.6/libs'
chmod 755 /usr/local/apache2/modules/libphp7.so
[activating module `php7' in /usr/local/apache2/conf/httpd.conf]
Installing shared extensions:     /usr/local/lib/php/extensions/no-debug-zts-20190902/
Installing PHP CLI binary:        /usr/local/bin/
Installing PHP CLI man page:      /usr/local/php/man/man1/
Installing phpdbg binary:         /usr/local/bin/
Installing phpdbg man page:       /usr/local/php/man/man1/
Installing PHP CGI binary:        /usr/local/bin/
Installing PHP CGI man page:      /usr/local/php/man/man1/
Installing build environment:     /usr/local/lib/php/build/
Installing header files:          /usr/local/include/php/
Installing helper programs:       /usr/local/bin/
  program: phpize
  program: php-config
Installing man pages:             /usr/local/php/man/man1/
  page: phpize.1
  page: php-config.1
/home/admin/php-7.4.6/build/shtool install -c ext/phar/phar.phar /usr/local/bin
ln -s -f phar.phar /usr/local/bin/phar
Installing PDO headers:           /usr/local/include/php/ext/pdo/

PHPのライブラリのいくつかは「/usr/local/include/php/」「/usr/local/lib/php/」のように、用途に応じて複数の配置場所へ配置されます。しかも今回PHP 7.4.10は、ラズパイのopenSUSEでも「/usr/local/lib64/php/」に配置されるのではなく、他のディストリビューションと同じ配置になったんです。なぜだかは知らないが、とりあえずPHP 7.4.10+openSUSE 15.1をラズパイで実装すると、lib64に配置されずlibディレクトリに配置されることがわかったんです。

また、この時点で、PHPのDLL(ダイナミックリンクライブラリ、外部拡張アプリケーションに該当する)は自動的にApacheのフォルダに配備されます

次に、PHPの環境設定ファイルのコピーを行います。
まずはphp.iniをPHPのライブラリフォルダ/usr/local/lib(openSUSEも含む)/にコピーします。

# cp php.ini-development /usr/local/lib/php.ini
# ls -l /usr/local/lib
合計 328
-rw-r--r-- 1 root root 144402  6月 24 12:34 libz.a
lrwxrwxrwx 1 root root     14  6月 24 12:34 libz.so -> libz.so.1.2.11
lrwxrwxrwx 1 root root     14  6月 24 12:34 libz.so.1 -> libz.so.1.2.11
-rwxr-xr-x 1 root root 113656  6月 24 12:34 libz.so.1.2.11
drwxr-xr-x 4 root root     37  6月 24 16:19 php
-rw-r--r-- 1 root root  72278  6月 24 16:21 php.ini
drwxr-xr-x 2 root root     21  6月 24 12:34 pkgconfig

Apache側の設定

Apacheで、PHPファイルが認識できるようにする必要があるので編集します。PHPのDLLは、PHPインストール時にhttpd.confで自動的に書き込まれるので追加不要です。httpd.conf側でやるべきことは、PHPのMIMEタイプがApacheで認識されればよいのです。

# vi /usr/local/apache2/conf/httpd.conf
/usr/local/apache2/conf/httpd.conf
<IfModule dir_module>
    DirectoryIndex index.html ← 「index.php」を追加
</IfModule><IfModule mime_module>
    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz
    …
    AddType application/x-httpd-php .php  ←   この行を追加
</IfModule>

PHPの環境設定

PHPの文字コードや参照ライブラリの設定を変えます。

# vi /usr/local/lib/php.ini
php.ini
# 内容が長いので、一部修正するもののみ、修正後のもののみを記載します。セミコロン「;」は外します。「;」外すだけの行も含めて記載されています
output_buffering = On
default_charset = "UTF-8"
include_path = ".:/usr/local/include/php:/usr/local/lib/php"
extension_dir = "/usr/local/include/php/ext"
date.timezone = Asia/Tokyo
mbstring.language = Japanese
mbstring.encoding_translation = Off
mbstring.detect_order = UTF-8, SJIS, EUC-JP, JIS, ASCII
mbstring.substitute_character = none

PHPの動作確認

PHP確認用のページ

まずは確認用のPHPページを作ります。

# vi /usr/local/apache2/htdocs/phpi.php
phpi.php
<?php phpinfo(); ?>

なぜPHPファイルを/usr/local/apache2/htdocs/に配置する??って聞かれますが、Apacheをソースコンパイルでインストールすると、Webページデータの格納フォルダは「/usr/local/apache2/htdocs/」がデフォルトだからです。まぁ、httpd.confで格納先を変更できますが、今回はそれは割愛します。

Apacheの再起動

# systemctl stop httpd
# systemctl start httpd
# systemctl status httpd

再起動しないとPHPのモジュールをロードした状態でApacheが動作しないので、一度止めてから、再スタートします。その後、statusで起動していることを確認します。
phpinfo.png

pdo.png

上の画像は仮想マシンのものですが、Raspberry Piでも同じようなphpinfoが表示されたので、PHPは使えるようになりました(*˘ᗜ˘*)
…ただ単に画像の用意が面倒だからやってないだけなんで。。。

次回

MySQLに接続して、PHPのWebアプリサーバーがデータベースを利用できるようにします。ラズパイではMySQLはサポートされていないので、レポジトリから直接簡単インストールすることはできず、インストールしたとしても、microSDの書き込み寿命を縮めるだけなので、次回はMySQLサーバーに接続できるかを検証します。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Raspberry PiでApache2.4+PHP7.4をソースコンパイルしてWebサーバー構築 - 1.Apache導入編

前提と準備

Linuxサーバー構築の記事

いつものPCやHyper-Vといった仮想マシンなど、x64向けのWebサーバー構築を前回は行っていましたが、今回はPCや仮想マシンではなく、Raspberry PiにApacheでWebサーバーで構築します(⑅•ᴗ•⑅)

ソースコードでコンパイルする意味

Apacheをどのディストリビューションでも同じように設定しやすいし、必要なバージョンを用意できるからです(パッケージの標準コマンドだけだと、そのディストリビューションのバージョンで変動する)。

しかし全部のパッケージをソースコンパイルすると、その大本のライブラリを全部探し回ることになるので、ApacheやPHPなど、どうしても固定して稼働したいものに限って、ソースコンパイルし、makeに必要なものについては、dnfやaptなどの標準パッケージコマンドで対応しています

環境

  • Webサーバープログラム:Apache 2.4.46(ソースコンパイル)
  • クライアント:Windows10 Pro
  • サーバーのアーキテクチャ:Raspberry Pi 3B+(armv8搭載) Linuxのディストリビューション:openSUSE 15.1 Leap(64bit) / Raspberry Pi OS 2020.08版(32bit)

前提

  • OSは最小限のインストール。また、最新の状態でOSをアップデートしていること
  • ユーザーはrootでインストール(私の検証ではadminという管理者アカウントにて、そこからsudoで処理しています)
  • openSUSEではファイアウォールはfirewalldを使う(ディストリビューション独自のファイアウォールコマンドは使用しない)。ラズパイのRaspberry Pi OSでは、firewalldについて、IPv6周りの連動が糞だったので、Debian系標準のufwを使用することにしました。

サーバー条件

IPアドレス

  • クライアント:192.168.1.11
  • Webサーバー:192.168.1.18(どのディストリビューションでも同じIPアドレスで検証)
  • 所属ネットワークセグメント:192.168.1.0/24 Webサーバー.png

パッケージを個別ダウンロードしてインストールする機能とバージョン(2020年6月時点)

  • zlib-1.2.11.tar.gz
  • apr-1.7.0.tar.gz
  • apr-util-1.6.1.tar.gz
  • httpd-2.4.46.tar.gz
  • php-7.4.10.tar.gz

それ以外の必要なパッケージは、ディストリビューションの標準パッケージコマンド(dnfやaptなど)でインストールし、個別ダウンロードは不要です。

ダウンロードについては、公式サイトにアクセスして、そこからダウンロードしてFTPで転送するか、ダウンロードファイルのURLさえわかれば、wgetで入手することもできますが、入手方法は省略しています。

作業手順

準備

makeやcmake、パッケージ解凍機能のインストール

openSUSE15.1(RaspberryPi)
# zypper -n install make cmake tar bzip2
RaspberryPiOS(2020.08)
# apt-get -y install make cmake tar bzip2

GCCとC++コンパイラのインストール

openSUSE15.1(RaspberryPi)
# zypper -n install gcc gcc-c++
RaspberryPiOS(2020.08)
# apt-get -y install gcc build-essential

zlibのソースインストール

zlibの配置場所はデフォルトのまま変えないでインストールしました。

# cd [zlibの書庫ファイルが置いてあるディレクトリ]
# tar zxvf zlib-1.2.11.tar.gz
# cd zlib-1.2.11/
# ./configure
# make
# make install

Apacheをコンパイルするために必要なパッケージをディストリビューション標準パッケージコマンドでインストール

PerlやSSLのライブラリなどをインストールすることで、Apacheで必要な機能をそろえることができます
面倒くさくても実行しないと、パッケージがない、とエラーが出てコンパイルが中止されるんです(´•ω•̥`)

openSUSE15.1(RaspberryPi)
# zypper -n install ncurses-devel perl libaio1 libaio-devel perl-Data-Dump libexpat-devel pcre pcre-devel libopenssl-devel
RaspberryPiOS(2020.08)
# apt-get -y install libncurses5-dev perl libaio1 libaio-dev libexpat1-dev libpcre3 libpcre3-dev libssl-dev

APRとそのユーティリティーライブラリをインストール

APRは/opt/apr-1.7.0に、APR-Utilは/opt/apt-util-1.6.1にライブラリをインストールします

# cd [apr-1.7.0.tar.gzが置いてあるディレクトリ]
# tar xvzf apr-1.7.0.tar.gz
# cd apr-1.7.0/
# ./configure --prefix=/opt/apr-1.7.0
# make
# make install

# cd [apr-util-1.6.1.tar.gzが置いてあるディレクトリ]
# tar xvzf apr-util-1.6.1.tar.gz
# cd apr-util-1.6.1/
# ./configure --prefix=/opt/apr-util-1.6.1 --with-apr=/opt/apr-1.7.0
# make
# make install  

Apache 2.4のソースコンパイルのインストール

さて、ここからが本番です。この作業は結構時間がかかりました。ラズパイだったので、40分ほどかかったかもしれないです。。

configureとmake

# cd [httpd-2.4.46.tar.gzが置いてあるディレクトリ]
# tar xvzf httpd-2.4.46.tar.gz
# cd httpd-2.4.46/
# ./configure --with-apr=/opt/apr-1.7.0 --with-apr-util=/opt/apr-util-1.6.1 --enable-so --enable-ssl --enable-mods-shared=all --enable-mpms-shared=all

そこで、configureの指定として、APRとAPR-Utilのパスは、インストールで指定したパスを指定します。ここではAPRは「/opt/apr-1.7.0」に、APR-Utilは「/opt/apr-util-1.6.1」にインストールしていて、それ使いました。

またSSLを有効にしています。

※ もしOpenSSLのパスを変えるには「--with-ssl=/usr/local/ssl」のように、インストール先を指定するのですが、私の環境ではOpenSSLはパッケージデフォルトのものを使っているので、特に変えていません。

私は上記の必要なパッケージをすべてインストールしたところ、エラーなくconfigureできました(*´꒳`*)さて、肝心なコンパイルとインストールです。そこでエラーが出たら、ただでさえ機能てんこ盛りなApacheなので、どこでエラーが出たかを探し回ると面倒です( ˙꒳​˙ᐢ )

# make
# make install

エラーなくコンパイルできれば、インストールは完了です♪(*˘︶˘*).。.:*♡

Apacheの環境設定

インストールできたら、さぁ次は設定ファイルです( ˙꒳​˙ᐢ )
ソースコンパイルでApacheをインストールすると、Apache本体は/usr/local/apache2にインストールされます。設定ファイルは/usr/local/apache2/conf/に格納されるので、その中にApacheの環境設定を行います。

[Apacheの基本設定]
# vi /usr/local/apache2/conf/httpd.conf
/usr/local/apache2/conf/httpd.conf
#ServerName www.example.com:80
ServerName localhost:80   ← この行を↑の直下に追記します
…
DocumentRoot "/usr/local/apache2/htdocs"
<Directory "/usr/local/apache2/htdocs">
    …
    Options Indexes FollowSymLinks
    ↑ 先頭に「#」を付けてコメントアウトします
   (ページとして公開されてないディレクトリは無駄なアクセスを許可しないこと)
…
#LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
#LoadModule ssl_module modules/mod_ssl.so
 ↑の2つの行を探して、いずれも「#」を消して、soライブラリを読み込みます
#Include conf/extra/httpd-ssl.conf
 ↑の「#」を消して、conf/extra/httpd-ssl.confを読み込めるようにします
[ApacheのSSL(https)の設定]
# vi /usr/local/apache2/conf/extra/httpd-ssl.conf
/usr/local/apache2/conf/extra/httpd-ssl.conf
SSLCertificateFile "/usr/local/apache2/conf/server.crt"SSLCertificateKeyFile "/usr/local/apache2/conf/server.key"

ここでは、httpsに必要な鍵の場所は、設定ファイルと同じ/usr/local/apache2/conf/に位置することにしました。

SSL証明書作成

本来は証明書をルート認証機関を経由しての作成ですが、ここではあくまでもApacheをhttpsに対応させる手法を優先させるので、証明書の発行機関は触れません。なのでアクセスするとセキュリティの警告は出ます【。。。】

# cd /usr/local/apache2/conf/
# openssl genrsa -out server.key 2048
# openssl req -new -key server.key -out server.csr

SSL鍵を作成するプロセスで、組織のプロフィールを入力する対話もありますが、以下の入力で問題なく証明書は作成できます

# openssl req -new -key server.key -out server.csr

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) []:<what entry=住んでいる都道府県 example=Kanagawa>
Locality Name (eg, city) [Default City]:<what entry=住んでいる市町村 example=Miura>
Organization Name (eg, company) [Default Company Ltd]:<what entry=任意の組織名>
Organizational Unit Name (eg, section) []:<what entry=任意の組織単位>
Common Name (eg, your name or your server's hostname) []:<what entry=ドメイン名 example=kazumi-jam.chips.jp>
Email Address []:<what entry=メールアドレス example=rei@example.com>

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:<what entry=とりあえず適当>
An optional company name []:<what entry=とりあえず空白Enter>

わかりやすく色分けしたいので、XML風に「何を入力すればいいか」を付け加えてみました(*˘︶˘*) XMLタグ風に「<what entry=…」となっているのは、何を入力すればいいのか「example=…」は入力の例です。なお実際は空白が入っていてもかまいません。

例:
State or Province Name (full name) []: Kanagawa Pref.
Locality Name (eg, city) [Default City]: Miura city

server.csrを作成し終えたら、証明書一式を作成します。

# openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt

「-days」オプションがないと90日間しか有効期間がないので実験目的以外では使い物になりません。なのでここでは一応10年間として「-days 3650」としています。それでも証明書自体がオレオレ証明書で信頼された機関から発行されたものではないですが…(*˘ᗜ˘*;)

さて、SSL証明書を作成したら、他の人に触れないように、パーミッションを変更します。

# chmod 600 /usr/local/apache2/conf/server.crt
# chmod 600 /usr/local/apache2/conf/server.csr
# chmod 600 /usr/local/apache2/conf/server.key
# ls -l /usr/local/apache2/conf/
合計 108
drwxr-xr-x 2 root root   313  6月 24 13:08 extra
-rw-r--r-- 1 root root 19316  6月 24 13:07 httpd.conf
-rw-r--r-- 1 root root 13064  6月 24 13:03 magic
-rw-r--r-- 1 root root 60847  6月 24 13:03 mime.types
drwxr-xr-x 3 root root    37  6月 24 13:03 original
-rw------- 1 root root  1379  6月 24 13:06 server.crt
-rw------- 1 root root  1119  6月 24 13:04 server.csr
-rw------- 1 root root  1675  6月 24 13:03 server.key

「ls -l」コマンドで、「server.crt」など証明書鍵関連の3ファイル(上のリストだと下3行)が、所有者rootでパーミッションが「rw-------(600)」であることを確認します。秘密鍵の中身が他のユーザーから見える時点でセキュリティ違反ですからね。。

Apacheサービスの起動

Apacheサービスの起動スクリプト作成&有効化

Apacheに必要な環境設定と鍵はそろいました。なので、起動できるようにしたいと思います。起動スクリプトはSystemdなので、/etc/systemd/systemに作成します

# cd /etc/systemd/system
# vi httpd.service
httpd.service
[Unit]
Description=Apache

[Service]
Type=forking
ExecStart=/usr/local/apache2/bin/apachectl start
ExecStop=/usr/local/apache2/bin/apachectl stop

[Install]
WantedBy=multi-user.target

ここではSystemdのスクリプトは詳しく説明しませんが、Apacheの起動ファイル本体は/usr/local/apache2/binにあるので、その中のApacheサービス起動の「apachectl」をコマンド実行することで、Apacheの起動や停止ができます。また起動と実行は、Apacheの場合は、Webサーバーのプロセスはサブプロセスとして実行される(要は、ある端末で起動実行すると「実行中」の状態になって他の操作ができなくなるのではなく、コマンド入力に戻って他の操作をそのまま実行できる。わかるかな??)ので、Typeはforkingを指定します。

ファイアウォールの設定

続いて、ポート80(http)と443(httpd)を受け付けます。
なお、前提の通り、サーバーとクライアントは192.168.1.0/24のネットワークに属しているので、それ以外の外部からのアクセスは受け付けないので、以下のようにrich ruleで許可します。

openSUSE15.1(RaspberryPi)(firewalld)
# firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="80" protocol="tcp" accept'
# firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="443" protocol="tcp" accept'
# firewall-cmd --reload
RaspberryPiOS2020.08(ufw)
# ufw allow proto tcp from 192.168.1.0/24 to any port 80
# ufw allow proto tcp from 192.168.1.0/24 to any port 443
# ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 30303/tcp                  ALLOW IN    192.168.1.0/24
[ 2] 5900:5999/tcp              ALLOW IN    192.168.1.0/24
[ 3] 80/tcp                     ALLOW IN    192.168.1.0/24
[ 4] 443/tcp                    ALLOW IN    192.168.1.0/24

起動と動作確認

それでは、起動します。enableでの常時起動有効化&statusで「Active」「Running」になっていることを確認。

# systemctl start httpd
# systemctl enable httpd
# systemctl status httpd

しかし…!!
openSUSEだと、systemctl start httpdでApacheの起動が失敗しました!!(´•ω•̥`)

openSUSE15.1(raspberryPi)
# journalctl -xe

上記コマンドで得られるジャーナルログを確認すると、Raspberry PiのopenSUSEでは、Apacheの設定ファイルで初期で指定されているユーザー「daemon」が存在しないことがわかりました。なので、Apacheのプロセスを起動するユーザーを新たに作成することにしました。。。

openSUSE15.1(raspberryPi)
# useradd -m apache
# passwd apache
# vi /usr/local/apache2/conf/httpd.conf

…(中略)…
User daemon    ← apacheに変更
Group daemon   ← usersに変更
…(中略)…

# systemctl start httpd

openSUSEでは、デフォルトではユーザーグループがユーザー名と同じで作成はなく「users」グループとして作成される。

これで「systemctl start httpd」で起動できるようになりました!!

Windowsクライアント側から、ブラウザでhttps://[LinuxサーバーのIPアドレス]/を入力して確認します。

ここではLinuxのWebサーバーは192.168.1.18なので、https://192.168.1.18にて。
もちろん証明書は信頼された機関発行ではないので、プライバシーエラーになります;;その際は「そのままアクセスする」を選んで先に進みます(ChromeやFirefoxでふるまいは違うけど。。)

itwks.png

上の画像は仮想マシンでやった場合のキャプチャですが、Raspberry Piでも上と同じ画面が出るので、成功です!!( ˶˙ᵕ˙˶ )

次回

PHPを導入して、Webアプリサーバーの基盤を掲載します

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ubuntu20.04とRaspberry PiでIPsecゲートウェイの簡易VPN構築 - 2.StrongSwan VPN接続確認

前提と準備

Linuxサーバー構築の記事

前回はStrongSwanのソースコンパイルによるIPsec-VPN環境の構築を行いましたが、今回はVPNに実際に接続できるか確認しましょう!(˶ ・ᴗ・ )੭⚐⚑

環境

  • IPsecプログラム:StrongSwan 5.9.0(ソースコンパイル)
  • IPsec交渉受信側:Raspberry Pi 3B+ / Raspberry Pi OS(2020/08版)(armhf(v7)、32bit)
  • IPsec交渉発信側:Hyper-V(第2世代)のx64仮想機 / Ubuntu 20.04(x86_64)
  • VPNに接続するクライアントとサーバーを別途用意(私はここではUbuntuとCentOSのWebサーバーを用意しました)

前提

  • OSは最小限のインストール。また、最新の状態でOSをアップデートしていること
  • ユーザーはrootでインストール(私の検証ではadminという管理者アカウントにて、そこからsudoで処理しています)
  • IPsecゲートウェイは、ファイアウォールはufwを使う(ラズパイのRaspberry Pi OSでは、firewalldについて、IPv6周りの連動が糞だったので、Debian系標準のufwを使用することにしました)

サーバー条件

IPアドレスとネットワーク構築図

  • IPsec交渉受信側ゲートウェイ(下の図の左、Raspberry Pi):

    • インターネット側(eth0):192.168.1.22
    • VPN領域側(eth1):192.168.2.1
  • IPsec交渉発信側ゲートウェイ(下の図の右、Ubuntu 20.04):

    • インターネット側(eth0):192.168.1.18
    • VPN領域側(eth1):192.168.5.1
  • ネットワークセグメント:

    • インターネット接続可能:192.168.1.0/24
    • Raspberry Pi(図の左の交渉受信側)セキュアセグメント:192.168.2.0/24
    • Ubuntu 20.04(図の右の「CentOS 8」と記載されている交渉発信側)セキュアセグメント:192.168.5.0/24
  • VPNに接続する端末:

    • クライアント(Ubuntu 20.04):192.168.2.2(192.168.2.0/24に属する)
    • Linux Webサーバー(CentOS 8.1):192.168.5.2(192.168.5.0/24に属する)
  • IPsec領域関連:

    • トンネリング区間:192.168.1.22 ~ 192.168.1.18間
    • VPN連携:192.168.2.0/24 ~ 192.168.5.0/24をVPN接続 IPsecゲートウェイ以内のVPNに接続する図 ※ 図の左上の「openSUSE」はRaspberry Pi OSに、右上の「Linuxルーター CentOS 8」はUbuntu 20.04に読み替えてください。

ここでは、192.168.2.2のUbuntuクライアントが、192.168.5.2のLinux WebサーバーにVPN接続できるかを試します。なおVPNに接続しているサーバーとクライアントともに、VPNの範囲のみ接続して、インターネットには接続しないこととします。

パッケージを個別ダウンロードしてインストールする機能とバージョン(2020年9月時点)

  • zlib-1.2.11.tar.gz
  • strongswan-5.9.0.tar.gz

それ以外の必要なパッケージは、ディストリビューションの標準パッケージコマンド(dnfやaptなど)でインストールし、個別ダウンロードは不要です。

ダウンロードについては、公式サイトにアクセスして、そこからダウンロードしてFTPで転送するか、ダウンロードファイルのURLさえわかれば、wgetで入手することもできますが、入手方法は省略しています。

作業手順

VPNにサーバーとクライアントを接続する

VPN領域内のIPアドレス割り振り

前回ではeth1はあくまでもネットワークアダプタを追加しただけであって、まだIPアドレスは割り振られていません。ラズパイの場合(Raspberry Pi OS)は/etc/dhcpcd.confを手動で追加するしかなかったんです。。もちろんdhcpcd.confにはデフォルトゲートウェイもDNSサーバーも指定があるので、複数指定するとネットワークの順位が混乱するので、新設したeth1には、IPアドレスのみを記載。

参照記事:

RaspberryPiOS(2020.08)
# vi /etc/dhcpcd.conf
/etc/dhcpcd.conf(RaspberryPiOS)
[以下のインターフェースの情報を最終行に追記]
#interface eth1
interface eth1
static ip_address=192.168.2.1/24
noipv6
RaspberryPiOS(2020.08)
# reboot

# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether [最初からあるネットワークアダプタのMACアドレス] brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.22/24 brd 192.168.1.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 [最初からあるネットワークアダプタのIPv6アドレス] scope global dynamic noprefixroute
       valid_lft 14373sec preferred_lft 12573sec
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether [増設ネットワークアダプタのMACアドレス] brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.1/24 brd 192.168.5.255 scope global noprefixroute eth1
       valid_lft forever preferred_lft forever
    inet6 [増設ネットワークアダプタのIPv6アドレス] scope link noprefixroute
       valid_lft forever preferred_lft forever

# ip route
default via 192.168.1.1 dev eth0 proto static metric 100
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.22 metric 100
192.168.2.0/24 dev eth1 proto kernel scope link src 192.168.2.1 metric 101

IPアドレスの設定ファイルってディストリビューション依存しすぎていて、慣れないと大変です٩(.› ‹.♡)۶
eth1にIPアドレスを設定しました。もちろんルーティングにも192.168.2.0/24も認識されました。

その一方で、Hyper-VのUbuntuだとSSHではなくGUI画面で設定できるから、そこにアドレスとネットマスクだけを指定して設定を保存するだけでOKです٩(.› ‹.♡)۶
secgw01_Ubuntuでのeth1追加方法.png

Ubuntu20.04(Hyper-V/x64)
# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether [最初からあるネットワークアダプタのMACアドレス] brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.18/24 brd 192.168.1.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 [最初からあるネットワークアダプタのIPv6アドレス] scope global temporary dynamic
       valid_lft 14043sec preferred_lft 12243sec
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether [増設ネットワークアダプタのMACアドレス] brd ff:ff:ff:ff:ff:ff
    inet 192.168.5.1/24 brd 192.168.5.255 scope global noprefixroute eth1
       valid_lft forever preferred_lft forever
    inet6 [増設ネットワークアダプタのIPv6アドレス] scope link noprefixroute
       valid_lft forever preferred_lft forever

# ip route
default via 192.168.1.1 dev eth0 proto static metric 100
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.18 metric 100
192.168.5.0/24 dev eth1 proto kernel scope link src 192.168.5.1 metric 101

VPN領域内のネットワークにサーバーとクライアントをLANケーブル接続する

これは言うまでもないですね。サーバーとクライアントをLANケーブルでつないで、IPアドレスを手動で設定します(DHCPサーバーがVPN領域内にないので、手動設定するしかないです)

「サーバー条件」を参照しての通り、下の図のようなLANケーブル接続でIPアドレスを割り振っていきます。もちろん仮想マシンの場合は仮想スイッチを割り当てるだけでOKです。

  • Ubuntuクライアントをラズパイに接続(192.168.2.0/24)。IPアドレスを192.168.2.2に設定
  • Linux WebサーバーをHyper-V仮想機に接続(192.168.5.0/24)。IPアドレスを192.168.5.2に設定 IPsecゲートウェイ以内のVPNに接続する図 ※ 図の左上の「openSUSE」はRaspberry Pi OSに、右上の「Linuxルーター CentOS 8」はUbuntu 20.04に読み替えてください。

VPNのネットワーク接続動作確認

Pingはこの時点で通っている

IPアドレスが適切なだけでもPingは通る
画面上はCentOS+openSUSEのものですが、今回のUbuntuを使うケースでも、クライアント(192.168.2.2)から対向のVPN領域にあるWebサーバー(192.168.5.2)に通るか確認したら、あっさり通っていました( ´థ౪థ)

やはりUbuntuのIPsecゲートウェイのケースでも、Webがその時点でVPN領域越しに見られるというわけじゃないみたいです。

この時点ではIPsec-VPN越しサーバーのwgetは不可
もちろんwgetでも「No route」となってしまうはずです

ufwの転送許可

IPsecでトンネリングしたパケットも、IPsecゲートウェイのufwでまた転送許可のルールを追加しなければならないので、VPNにあるサーバーとクライアントが通信するポートを開放した。ここでは、クライアントが192.168.2.2、サーバーが192.168.5.2なので、192.168.2.0/24 → 192.168.5.0/24宛ての転送許可をルールに加えるが、ufwの場合はrouteを指定する必要がある。

Webサーバーが使うポートは、Webである80・443・8080・8443なので、当然以下のコマンドを入力すればVPN越しにIPsecゲートウェイが転送してくれるはず。

[192.168.2.0/24 → 192.168.5.0/24 HTTP 許可]
# ufw route allow from 192.168.2.0/24 to 192.168.5.0/24 port 80 proto tcp
[192.168.2.0/24 → 192.168.5.0/24 HTTPS 許可]
# ufw route allow from 192.168.2.0/24 to 192.168.5.0/24 port 443 proto tcp
[192.168.2.0/24 → 192.168.5.0/24 ポート8080 許可]
# ufw route allow from 192.168.2.0/24 to 192.168.5.0/24 port 8080 proto tcp
[192.168.2.0/24 → 192.168.5.0/24 ポート8443 許可]
# ufw route allow from 192.168.2.0/24 to 192.168.5.0/24 port 8443 proto tcp

[確認するには]
# ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 30303/tcp                  ALLOW IN    192.168.1.0/24
…(中略)…
[10] 192.168.5.0/24 80/tcp      ALLOW FWD   192.168.2.0/24
[11] 192.168.5.0/24 443/tcp     ALLOW FWD   192.168.2.0/24
[12] 192.168.5.0/24 8080/tcp    ALLOW FWD   192.168.2.0/24
[13] 192.168.5.0/24 8443/tcp    ALLOW FWD   192.168.2.0/24
…(中略)…

参照:

Hyper-V仮想マシンのCentOS 8.1ではfirewalldとdirectの相性が悪い(具体的には、たぶんnftablesとの登録がうまくいっていないみたい)ために、転送ルールをfirewalldに登録してもうまく転送できない問題が発生していたが、Ubuntu20.04とRaspberry Pi OS(2020/08版)のufwではまだそういう問題が発生していなく、今後Debian系のOSはnftablesを推奨するので、早期にnftablesと転送ルールの問題が解決しなければ、CentOSの二の舞になるかもしれませんが…

nftables関連でいろいろ参考させていただきました!( ´ •̥ ̫ •̥ ` )- ̗̀ ♡ ̖́-

Webサーバーにアクセスできるか確認

IPsecゲートウェイの両方で転送を許可できたら、VPN越しにクライアントからVPN内のサーバーにアクセスできるかやってみました。

サーバーアクセス成功

この成功画面では、CentOS+openSUSEの場合での画面ですが、実際Ubuntuでもうまくいっています!!

セキュリティ確認

IPsecゲートウェイをまたぐパケットは暗号化されている??

やはり、Ubuntuの場合でも、下の画面みたいにパケットがIPsecトンネルでは暗号化を確認しています(˶ ・ᴗ・ )੭♡♡

パケットがIPsec暗号化されている!

わかりやすくHTTP(ポート80)で「QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ…」をHTTPSで暗号化させずにクライアントでサーバーからページをアクセスしてみたけど、IPsecゲートウェイ間のトンネリングでそれを拾ってみてみると、暗号化されていました!!

まとめ

StrongSwanでRaspberry Pi OSとHyper-V仮想マシンのUbuntu 20.04でも、IPsecゲートウェイの構築を行い、IPsec-VPNとしての用途を満たすことは確認した。やはりセキュリティ対策についてもCentOSの場合ともやはり変わらないことはわかったが…今後はnftablesのufwやfirewalldとの相性の課題もまだあるみたいだし…⸝⸝ᵕ ᵕ⸝⸝

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Javaでcronのプログラムを作ろう!!(TaskScheduler)

Java(cron4j)

・cronとは、多くのUNIX系OSで標準的に利用される常駐プログラム(デーモン)の一種で、利用者の設定したスケジュールに従って指定されたプログラムを定期的に起動してくれるもの。(*IT用語辞典参照)

jar

下記リンクからjarファイルをダウンロードしてIDEに設定しよう!!
https://www.sauronsoftware.it/projects/cron4j/download.php

Taskクラス

まず、実行したい処理を書くクラスを作ろう!!

CronTask
import java.util.Date;

public class CronTask implements Runnable{

    @Override
      public void run() {
        System.out.println(new Date()+": Hiiiii! cron4j!");
      }

}

Schedulerクラス

MyCronAppTest
import it.sauronsoftware.cron4j.Scheduler;

public class MyCronAppTest {

      public static void main(String[] args) {
        MyCronAppTest app = new MyCronAppTest();
        try {
          app.schedulerSimple();
          System.out.println("Press Ctrl+C to stop.");
          Thread.sleep(100000000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }

      public  void schedulerSimple() {
        Scheduler scheduler = new Scheduler();
        // every minute.
        scheduler.schedule("* * * * *", new CronTask());
        // start cron4j scheduler.
        scheduler.start();
      }
}

おまけ(Servletを使ったScheduler)

HelloServlet
import java.io.IOException;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import it.sauronsoftware.cron4j.Scheduler;

public class HelloServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

        public  void schedulerSimple() {
        Scheduler scheduler = new Scheduler();
        // every minute.
        scheduler.schedule("* * * * *", new CronTask());
        // start cron4j scheduler.
        scheduler.start();
      }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        MyCronApp app = new MyCronApp();
        try {
          app.schedulerSimple();
          System.out.println("Press Ctrl+C to stop.");
          Thread.sleep(100000000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        response.getWriter().append("Hello Servlet");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Javaでcronのプログラムを作ろう!!(タスクスケジューラー)

Java(cron4j)

・cronとは、多くのUNIX系OSで標準的に利用される常駐プログラム(デーモン)の一種で、利用者の設定したスケジュールに従って指定されたプログラムを定期的に起動してくれるもの。(*IT用語辞典参照)

jar

下記リンクからjarファイルをダウンロードしてIDEに設定しよう!!
https://www.sauronsoftware.it/projects/cron4j/download.php

Taskクラス

まず、実行したい処理を書くクラスを作ろう!!

CronTask
import java.util.Date;

public class CronTask implements Runnable{

    @Override
      public void run() {
        System.out.println(new Date()+": Hiiiii! cron4j!");
      }

}

Schedulerクラス

MyCronAppTest
import it.sauronsoftware.cron4j.Scheduler;

public class MyCronAppTest {

      public static void main(String[] args) {
        MyCronAppTest app = new MyCronAppTest();
        try {
          app.schedulerSimple();
          System.out.println("Press Ctrl+C to stop.");
          Thread.sleep(100000000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }

      public  void schedulerSimple() {
        Scheduler scheduler = new Scheduler();
        // every minute.
        scheduler.schedule("* * * * *", new CronTask());
        // start cron4j scheduler.
        scheduler.start();
      }
}

おまけ(Servletを使ったScheduler)

HelloServlet
import java.io.IOException;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import it.sauronsoftware.cron4j.Scheduler;

public class HelloServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

        public  void schedulerSimple() {
        Scheduler scheduler = new Scheduler();
        // every minute.
        scheduler.schedule("* * * * *", new CronTask());
        // start cron4j scheduler.
        scheduler.start();
      }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        MyCronApp app = new MyCronApp();
        try {
          app.schedulerSimple();
          System.out.println("Press Ctrl+C to stop.");
          Thread.sleep(100000000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        response.getWriter().append("Hello Servlet");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

IPエイリアスに対して、ssh でポートフォワード出来るって知ってました?

聞いてみると、けっこう知らない人が多かったので、書いときます。

タイトルに書いたとおり、IPエイリアスに対して ssh でポートフォワードが出来ます!

これだけだと、ちょっと意味わかりにくいですよね。
つまり、複数の宛先に対して、同一ポート番号での フォワード処理が出来るってことです。

例えば、サーバAの 443番(https)に向けた通信と サーバBの 443番(https)に向けた通信を、物理NIC を追加することなく、また、ローカルの監視ポート番号を変えることなく、1台のサーバで、単一コマンドにてフォワード出来るんです。
もちろん、443番に限らず、どんなポート番号でも同じです。

# ifconfig eth0 aaa.aaa.aaa.aaa ...

と 物理NICに設定されていたとして、

# ifconfig eth0:0 xxx.xxx.xxx.xxx
# ifconfig eth0:1 yyy.yyy.yyy.yyy
# ifconfig eth0:2 zzz.zzz.zzz.zzz

と、IPエイリアスを追加設定したとします。

ここで、特権ポートなんで root で、

# ssh -L aaa.aaa.aaa.aaa:443:localhost:1443 -L xxx.xxx.xxx.xxx:443:localhost:2443 -L yyy.yyy.yyy.yyy:443:localhost:3443 -L zzz.zzz.zzz.zzz:443:localhost:4443 user@server

と 出来るということです。

当然 このあと、多段転送で 目的のサーバにフォワードさせていくわけですが、
上の転送が出来るメリットは、通信ポートが変えられないアプリケーションを使っていた場合に、威力を発揮します。
特に、Windowsアプリは ポートを変えられないケースが多いですね。
そんな場合にも、aaa.aaa.aaa.aaa の 443番と、xxx.xxx.xxx.xxx の 443番 等を、同時に 使えるんです!

さらに、Windows 上にて!

コントロールパネルの ネットワーク設定で、物理NIC に 複数のIPアドレスを付与できますよね?
ここで、Cygwin の ssh でも 同様の処理が出来ます

例えば これと併用すると...

OpenBlocks を使い、遠隔地のインターネット公開されていない内部ドメインのWebサーバを、SSL-VPN装置を使わずに 安全に利用するには(OpenBlocks を、簡易VPN機器っぽく使う)
遠隔地から 内部ネットワークの複数サーバに向けて、さらに VPN っぽく遠隔利用できるわけです。

便利な世の中になったもんです。(って、昔から です)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む