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

Nginx について纏めてみる

Linuc2の学習のために、Nginxについて纏めてみる。
Apacheと同じぐらい利用するが、こちらもあまり細かな設定までは気にしたことがないので、纏めてみた。

インストール

私は Amazon Linux2 を良く使いますが、Amazon Linux2 では標準で Nginx の yum 向けパッケージが提供されていません。

そのため、↓の手順で追加する必要がある。

Amazon Linux 2にExtrasレポジトリからNginxをインストールする

主な設定ファイル

ファイル 説明
/etc/nginx/nginx.conf メイン設定ファイル
/etc/nginx/conf.d/default.conf デフォルトサーバーの設定ファイル
/etc/nginx/conf.d/ssl/conf SSLの設定ファイル
/etc/nginx/conf.d/virtual.conf バーチャルホストの設定ファイル

基本書式 : ディレクティブ 値;

ブロック構造をとるディレクティブもあります。
親ブロックで設定した内容は子ブロックにも引き継がれます。

ディレクティブ{
他のディレクティブ; 
 ...
}

ディレクティブ 説明 コンテキスト
include 他の設定ファイルを読み込む 全て
user ワーカープロセスの実行ユーザー main
worker_processes ワーカープロセス数 main
worker_connections 1つのワーカープロセスが同時に処理できるコネクション数 events
log_format アクセスログの書式定義 http
access_log アクセスログのパスとログレベル http,server,location
error_log エラーログファイルのパスとログレベル main,http,server.location
listen リクエストを受け付けるポート番号 server
server_name サーバー名 server
keepalive_requests 一度の接続で受け付けることのできるリクエスト数の上限 http,server,location
keepalive_timeout キープアライブのタイムアウトまでの秒数 http,server,location
server_tokens バージョン番号の表示 http,server,location
root ドキュメントルート http,server,location
index インデックスファイル http,server,location
autoindex インデックスリスト表示のon/off http,server,location
error_page エラーコードとエラーページノURI http,server,location
rewrite リダイレクトの設定 server,location

コンテキスト内には様々なディレクティブでパラメータを指定します。

例えば、別のサイトへリダイレクトさせるには、次のように設定します。
※一時的なリダイレクトの場合は、permanent を redirect に書き換えます。

server {
  listen 80;
  server_name www.example.com;
  rewrite ^(.*)$ http://www.example.net$1 permanent;

SSL/TLS

SSL関連のディレクティブ 説明
ssl onなら有効
ssl_certificate サーバー証明書ファイル、中間CA証明書ファイル
ssl_certificate_key サーバー秘密鍵ファイル
ssl_protocols バージョン
ssl_ciphers 暗号アルゴリズム
nginx.conf
http {
  ssl_ciphers:ECDHE-RSA-AES128-SHA;
  ssl_protocols TLSv1.2;
  ssl_prefer_server_ciphers on;
  ssl_session_tickets off;
  ssl_stapling on;
  ssl_stapling_verify on;
}

server {
  ssl on;
  listen 443 ssl;
  server_name www.example.com;
  ssl_certificate ssl/server.crt;
  ssl_certificate_key ssl/server.key;
  root /var/www/html;
  location / {
    index  index.html index.htm;
}

Nginx で ssl_protocols や ssl_ciphers を省略するとどうなるのか?

リバースプロキシ

リバースプロキシ関連のディレクティブ 説明
proxy_pass プロキシ先URI
proxy_http_version httpのバージョン
proxy_set_header プロキシ先に送られるリクエストヘッダの定義
nginx.conf
server{
  listen 80 default_server;
    server_name www.example.com;

    location / {
        proxy_pass    http://192.168.0.1;

        proxy_set_header    1.1;
        proxy_set_header    Host $http_host;
        proxy_set_header    X-Real-IP $remote_addr;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

クライアントからのアクセスではなく、リバースプロキシからのアクセスが記録されてしまいます。
そこでヘッダーを書き換えて、本来のアクセス元をWebサーバーが記録できるようにするためには、
proxy_set_header ディレクティブで、Hostヘッダ、X-Real-IPヘッダー、X-Forwarded-Forヘッダーを定義します。

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

Linaxのコマンドをまとめました。

はじめに

個人アプリの開発を進めていく中で、環境構築をする際Linaxkコマンドに触れることが多くなってきた為、備忘録もかねて今までに出てきたコマンドをまとめました。

ディレクトリに関するコマンド

コマンド 説明 使用例
cd ディレクトリ(フォルダ)移動 cd 移動したいフォルダ名
ls フォルダの内容をリスト形式で表示する 中身をみたいフォルダに移動して、ls
pwd 現在いる位置を表示する 現在いる位置を表示する
mkdir フォルダを作成する  mkdir フォルダ名
touch ファイルを作成する touch ファイル名
rmdir 空のフォルダを削除する rmdir フォルダ名
rm ファイルやフォルダを削除する mv
mv ファイルを移動 mv (移動元ファイル名/フォルダ名) (移動先ファイル名/フォルダ名) 
cat デファイルの内容を表示する cat ファイル名
grep 指定した文字列がテキスト内に存在した場合その行を抽出する grep "検索したい文字" * ファイル名
chmod ファイルやフォルダのアクセス権限を変更する chmod 権限ファイル名
chown ファイルやフォルダのオーナーやグループを変更する chown 変更したいユーザー名 変更したいファイル名
find ファイルの検索をする find / -name ファイル名
diff ファイルとファイルの内容の違いを表示する diff 旧ファイル名 新ファイル名
history コマンドの履歴を表示する -
ln ファイルやフォルダにリンクを設定する ln リンク元ファイル名 リンク先ファイル名/フォルダ名
apropos manページの内容を検索する apropos キーワード
less テキストファイルを閲覧する less ファイル名
more ファイルをページ単位で閲覧する more ファイル名 
clear 消さずに画面を綺麗にする -

mv (移動元ファイル名/フォルダ名) (移動先ファイル名/フォルダ名) 

ネットワーク関連を設定したい時

コマンド 説明
ssh sshでログインする
ftp ファイルをFTPで転送する
route ルーティングの表示や設定を行う

システム管理したい時

コマンド 説明
free 空きメモリや、使用中メモリを表示する
last ファイルをFTPで転送する最近ログインしたユーザー名を表示する
finger ユーザー情報を表示する

ユーザー管理したいとき

コマンド 説明
useradd/adduser ユーザーを新規作成する
deluser ユーザーを削除する
groupadd グループを新規作成する
groupdel グループを削除する
groupadd ルーティングの表示や設定を行う
chfn ユーザー情報を変更する

コマンドのオプションや使用方法を知りたいとき

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

RailsでTimecop/TimeHelpersを使って時刻を変える方法について

この記事は、Happy Elements Advent Calendar 2020の5日目です。
RailsでTimecop/TimeHelpersを使って時刻を変える方法についての記事です。

はじめに

ソーシャルゲームでは、イベントが yyyy年mm月dd日に始まるなど、特定の時刻になると発動することが定番です。

例: 架空のソーシャルゲームのイベントカレンダー
image.png

これらのようなイベントの動作を確認するために、サーバ側で時刻を変えることができると、動作テストがしやすくなります。
- 例1 12月2日 15:00開始のガチャAの動作確認をするために、サーバの時間を12/2 16時にセットする
- 例2 バグ報告があったので、1ヶ月前のイベントの時間にセットしてバグ調査をする など

サーバ側で時刻を変える方法について、以下の3つの方法に絞って調査しました。
- Timecop
- ActiveSupport::Testing::TimeHelpers
- libfaketime

この記事では、それぞれがどのようなものか、をまとめました。

Timecop

https://github.com/travisjeffery/timecop
こちらはRailsのgemです。
Time/Date/DateTimeクラスのオーバーライドとして実装されているものでした
https://github.com/travisjeffery/timecop/blob/master/lib/timecop/time_extensions.rb

調査を進めると、TimeHelpersという物がRailsに組み込まれていることがわかりました。
TimeHelpersは、Timecopより機能としては少なく、時刻を固定させるのみです。
Timecopは、固定の他に、過去や未来に設定した後に時刻が進むなども可能です。

TimecopとTimeHelperでは、Timecopの方がリッチな機能である、と言えると思います。

  • 標準のTimeHelpersで十分である
  • gemを入れたくない

などの場合は、TimeHelpersの利用が選択肢に上がってくると思います。
2020年現在もメンテナンスはされているようです。

ActiveSupport::Testing::TimeHelpers

https://edgeapi.rubyonrails.org/classes/ActiveSupport/Testing/TimeHelpers.html

Rails4.1以降で標準のものです。
時刻を固定・解除するのみです。

libfaketime

https://github.com/wolfcw/libfaketime

こちらはRailsの話ではなく、OSにインストールして動くサービスです。
システムコールを改変するものです

  • メリット
    • プログラムを変えなくていい
  • デメリット
    • 導入が少し手間

システムコールとは?

libfaketimeでシステムコールの話が出てきたので、ここではシステムコールについて。

strace というコマンドを使って、コマンドを打つと大量にログが出てきます。これがシステムコールです(fstat, close, read, ...etc)。
libfaketimeは、このシステムコールを書き換えて時刻を変えるので、TimecopやTimeHelpersよりも深い部分で動いていると言えると思います。

strace date

execve("/bin/date", ["date"], 0x7ffc3bc97870 /* 28 vars */) = 0
brk(NULL)                               = 0x55b92bdc6000
openat(AT_FDCWD, "/usr/local/lib/faketime/libfaketime.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0$\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=66512, ...}) = 0
...
read(4, "@2020-6-16 20:30:00\n", 4096)  = 20
close(4)                                = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}) = 0
write(1, "Tue Jun 16 20:30:00 JST 2020\n", 29Tue Jun 16 20:30:00 JST 2020
) = 29
close(1)                                = 0
close(2)                                = 0
munmap(0x7f46f7935000, 8)               = 0
munmap(0x7f46f7936000, 32)              = 0
exit_group(0)                           = ?
+++ exited with 0 +++

余談

調査中に、もしTimecopとlibfaketimeを同時に使った場合どうなるのだろう、と思いました。
実験してみたところ、Timecopで設定した時刻がRailsでは得られました。

libfaketimeで改変された時間を、さらにTimecopが上書きするという順序になります。
イメージ図は以下の通りです。

image.png

まとめ

自分が運営中のタイトルでは、開発者の手元では、TimeHelpersを使ってRailsの時刻を変えながらイベントの動作確認などに利用しています。libfaketimeも使えるようになっており、必要であればそちらも利用しています。
こちらの記事では、サーバ側で時刻を変える方法について、Timecop, TimeHelpers, libfaketimeを調査しました。
調査してわかりましたが、どれが優れているというものではありませんでした。
それぞれ、やりたいことの要件に合わせて選択すれば良いと思いました。
もしRailsで時刻を変えたいけど、どうしようと悩んで調べている方がいらっしゃいましたら、
参考にしていただけると幸いです。

(注) 記事の中の図は自分で用意しました

参考

https://andycroll.com/ruby/replace-timecop-with-rails-time-helpers-in-rspec/
https://techracho.bpsinc.jp/penguin10/2018_12_25/67780
https://qiita.com/ktrkmk/items/b1361dd43d22dcf5627e
https://qiita.com/Targityen/items/67682d6c80cdcbe1186c

終わりに

Happy Elements株式会社 カカリアスタジオでは、
いっしょに【熱狂的に愛されるコンテンツ】をつくっていただけるメンバーを大募集中です!

もし弊社にご興味持っていただけましたら、是非一度
下記採用サイトをご覧ください。
https://recruit.happyelements.co.jp/

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

gigafile便に上がっているファイルをwgetする

gigafile便のファイルをwgetでダウンロードしたい

gigafileで100GB近い動画ファイルを送られ、クラウドで再エンコードしてからダウンロードしようとしたところ、cookie関連を知らなくて調べるのにちょっと時間かかったのでメモ

gigafile便のダウンロードボタンのPHPはcookieを使っているみたいで、こうして一旦ダウンロードページのcookieを保存しておく必要があるようです

$ wget --keep-session-cookies --save-cookies=cookies.txt 【ダウンロードページのリンク】
$ wget --load-cookies cookies.txt -r -k -E 【ダウンロードボタンのリンク】

この二行でDLが始まります

時間帯によるけど観測した中では最高80MB/sくらいでダウンロードできてました、いいですねぇ

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

「俺の仮想マシンルーターがこんなに速いはずはないわ」と思って作った件

概要

この記事は @tnishinaga さんの「俺の仮想マシンルーターがこんなに遅いはずはない/ KernelVM online 1」のタイトルを若干パクってオマージュしたものになります。
「とりあえずそれなりに妥協して動けばいいや」という具合なのでセキュリティとかいろいろ考慮してないのでご了承ください。

(始めに言っておく)まとめ

いくら VirtIO を有効にしていてもオーバーヘッドとか VM に載せる OS が違ったりすると速度が上がるわけじゃないかもしれないよ

きっかけ

以前書いた願望」より

そろそろ仮想化に意欲的になったり「IPv6 IPoE」に興味を持ったりしますが、ハードの予算は取れないしガラケーの需要も減りつつあるし周りも「は? 新しいハード? インフラ? インターネットなんてできりゃいいじゃん、そんなのに金使うくらいなら(ry」という感じでかなり消極的だったりですがいつかは新鯖投入して「今使っている PC ルーターの仮想化」に挑戦したいですね(いつとは

買いました

ヤフオクと某なんちゃら給付金を用いて買いました。

  • NEC Express5800/S70 タイプRB(@ヤフオク)
    • CPU: Xeon X3430
    • メモリ: 9[GB]
    • GPU: Quadro FX570
    • HDD: 320[GB]
  • Gigabit LAN カード,Broadcom BCM5751純正ボード1 x2(@amazon.co.jp)

トータルで3万円ぐらいですが、12年前に組んだ Cerelon PC ルーターより安くてグレードが高k(ry

セットアップ

  • みんな大好き CentOS 7 x86_64 を Express5800 に
    • VM のホストにグローバルな IPv6 のアドレスを付けてなにかやることがないのでローカルホスト以外つけていません。
  • VM のゲストにルーターをポンと構築
    • 「まぁ多少のオーバーヘッドはしょうがないかー」精神で
    • 「フレッツ光ネクスト ギガラインタイプ」相当の線にしたのでどうせなら「フレッツ光ネクスト ハイスピードタイプ」の上限 200[Mbps]以上が出ればほぼ十分
  • とりあえず PPPoE のやりとり用に FreeBSD、IPoE のやりとり用に Debian
    • 両方 FreeBSD が良かったのですが早く IPoE の線でいろいろ遊びたくてファイアウォールのルールがネットで転がっている Linux に
    • 最後のまとめの方にも書いていますが最終的に FreeBSD だけ VirtIO を無効にして e1000e にしています
  • ブリッジは OpenvSwitch
    • macvtap でも良かったのですが「OpenvSwitch にフレッツ直結してみた」という一例が見当たらなかったし面白そうだったので OpenvSwitch にしたのもひとつあります

ネットワーク構成 / 計測条件

network.png

計測サイトは以下を使用しました。

計測結果

iperf3.png
SPEEDTEST by RBB.png
FreeBSD の VM で VirtIO を有効にして PPPoE で外とのやりとりをしたらダウンの速度は出るけどアップの速度が出ないという結果に。それ以外はまぁまぁなところなのかなと
ただ、たまたま FreeBSD で ookla のスピードテストを走らせるとアップの速度が出るようなのでファイアウォール(の PF)あたりがなにか悪さしてるのではないかといらぬ推測をしてみたり・・・
何はともあれとりあえず VirtIO ではなく e1000e にしてお茶を濁すことにして、v4 over v6 のルーターを作ればいいかということにしました。v4 PPPoE でもまぁまぁ使えてますしw

まとめ

いくら VirtIO を有効にしていてもオーバーヘッドとか VM に載せる OS が違ったりすると速度が上がるわけじゃないかもしれないよ

おまけ

VPS とかパブリッククラウドなサービスを使ってるわけではないの Public な iperf のサーバーを探して使いましたが日本国内には正直見つからなったのでどなたかやらないですかね?(SoftEther さんや JANOG で見かけた i-measure な皆さんを遠目で見ながら


  1. 追加で HDD を投入した関係で Intel NIC だと若干お高くなったので妥協しました。「蟹は嫌だ…蟹は嫌だ嫌だ…!」「BroadCom!!」 

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

【コピペOK】基本的なLinuxコマンド集【18選】


最近、LAMP環境構築を行っているのですが、その中でLinuxコマンドに多く触れる機会があり、知識のストックも溜まってきたので、今回はコマンドの中でも頻出のものを解説していこうと思います。



予備知識

ディレクトリ

簡単に言えばフォルダのこと。

ルートディレクトリ

そのコンピュータ内の全ディレクトリ、ファイルを格納しているディレクトリ。

ホームディレクトリ

ユーザーが抱える全ディレクトリ、ファイルを格納しているディレクトリ。

カレントディレクトリ

現在作業しているディレクトリ。

絶対パス

ルートディレクトリから見たファイルパス。

相対パス

現在作業中のディレクトリから見たファイルパス。





参照系

pwd

ホームディレクトリから、現在作業中のファイルパスを表示。

【記述例】

$ pwd


【出力例】

/Users/username




ls

現在作業中のディレクトリの、保存されているファイルやディレクトリの一覧を表示。

【記述例】

<!-- 一覧を表示 -->
$ ls

<!-- 隠しファイル(. から始まる)も含めて表示 -->
$ ls -a

<!-- 権限などの詳細情報を表示 -->
$ ls -l

<!-- 隠しファイルも含めて権限などの詳細情報を表示 -->
$ ls -la


【出力例】

<!-- ls -->
Desktop             Sinatra
Documents           Sites
...

<!-- ls -a -->
.Trash              Documents
.bundle             Downloads
...

<!-- ls -l -->
drwx------@  5 username  username   160 11 14 16:12 Applications
drwx------@  9 username  username   288 11 24 19:55 Desktop
...

<!-- ls -la -->
drwx------   2 username  username     64 11 21 14:01 .Trash
drwxr-xr-x   4 username  username    128 10 20 23:12 .bundle
...




cat

ファイルの中身を表示。スクロールはできないので、1画面に収まるような分量の内容の場合に使用。

【記述例】

$ cat exampleFile


【出力例】

<!-- exampleFileの中身の記述 -->
これは見本です。




less

ファイルの内容を表示。スクロールが可能。1画面以上の分量の内容の場合に使用。

【記述例】

$ less exampleFile


【出力例】

<!-- exampleFileの中身の記述 -->
これは見本です。
.
.
.




history

実行したコマンドの履歴を表示。

【記述例】

<!-- コマンドの履歴を表示 -->
$ history

<!-- 最新のコマンドを5つ表示(数字は任意) -->
$ history 5

<!-- historyで表示されたナンバリングに対応するコマンドを実行(数字は任意) -->
$ !5

<!-- historyで表示されたナンバリングに対応するコマンドを履歴から削除(数字は任意) -->
$ history -d 5


【出力例】

<!-- history -->
  .
  .
  .
  848  pwd
  849  pwd
  850  ls
  851  ls -a
  852  ls -l
  853  ls -la
  854  cat
  855  ls

<!-- history 5 -->
  851  ls -a
  852  ls -l
  853  ls -la
  854  cat
  855  ls

<!-- !855(上記なら ls を実行) -->
Desktop             Sinatra
Documents           Sites
...

<!-- history -d 853 -->
<!-- 853 ls -laを削除 -->
  .
  .
  .
  851  ls
  852  ls -a
  853  ls -l
  854  cat
  855  ls






作成系

mkdir

カレントディレクトリ内に、ディレクトリを新規作成。

【記述例】

$ mkdir exampleFile




touch

カレントディレクトリ内に、ファイルを新規作成。

【記述例】

$ touch exampleFile






削除系

rm

ファイルやディレクトリの削除。通常は出力無しですが、ファイルやディレクトに記述や保存がされている場合、Y(yes)N(no) で実行確認を要求されます。

【記述例】

<!-- ファイルの削除 -->
$ rm exampleFile

<!-- ファイルの強制削除(確認無し) -->
$ rm -f exampleFile

<!-- ディレクトリの削除 -->
$ rm -r exampleDirectory

<!-- ディレクトリの強制削除 -->
$ rm -rf exampleDirectory




複製系

cp

ファイルやディレクトリのコピーを作成。

【記述例】

<!-- exampleFile を exampleFile2 としてコピー作成 -->
$ cp exampleFile exampleFile2

<!-- exampleDirectory を exampleDirectory2 としてコピー作成 -->
$ cp -r exampleDirectory exampleDirectory2




移動系

cd

カレントディレクトリ(現在作業中のディレクトリ)の移動。絶対パスか相対パスで指定可能。

【記述例】

<!-- ホームディレクトリに移動 -->
$ cd

<!-- exampleDirectory に作業場所を移動 -->
$ cd exampleDirectory

<!-- 一階層上のディレクトリに移動 -->
$ cd ..




mv

ファイルの移動や、ファイル名の変更が可能。絶対パスか相対パスで指定可能。

【記述例】

<!-- exampleDirectory1 にある exampleFile1 を exampleDirectory2 に移動 -->
$ mv exampleDirectory1/exampleFile1 exampleDirectory2

<!-- exampleFile2 の名前を exampleFile3 に変更 -->
$ mv exampleFile2 exampleFile3




便利系

clear

画面をリフレッシュする。

【記述例】

$ clear

または「control」+「L」でも可能。



shutdown

OSをシャットダウンする。

【記述例】

$ shutdown -h now






ユーザー系

useradd

ユーザーの新規追加。(この時、ユーザー用のホームディレクトリも作成される)

【記述例】

<!-- example と言うユーザー名でユーザー新規作成 -->
$ useradd example




passwd

新規作成したユーザーのパスワードを新規登録、既存のユーザーのパスワード変更。(本番環境では"鍵認証"と言う別の認証方法を利用する事が多い)

【記述例】

<!-- example と言うユーザー名のパスワードを変更 -->
$ passwd example




userdel

ユーザーの削除。

【記述例】

<!-- example ユーザーの削除 -->
$ userdel example

<!-- example ユーザーの削除と、削除したユーザーのホームディレクトリも削除 -->
$ userdel -r example




su

ユーザーの切り替え。

【記述例】

<!-- example ユーザーに切り替え(カレントディレクトリは同じ) -->
$ su example

<!-- example ユーザーに切り替え(そのユーザーのホームディレクトリから開始) -->
$ su - example




exit

ユーザーのログアウト。多重にログインしている場合は、元のユーザーに戻る。

【記述例】

<!-- 現在使用しているユーザーのログアウト -->
$ exit






まとめ

Linuxディストリビューション(Linux系のOS)での環境構築などをする際は、頻繁にLinuxコマンドを使用するので、解説した基本的なコマンドは、ある程度使い慣れておくと役立ちます。

macなら「ターミナル」
Windowsなら「Power Shell」
これらで実行できますので、ぜひお試しください。

最後までご覧いただき、ありがとうございました!





筆者:yuki|学習10日目で初案件獲得→現在はフルスタックエンジニア転職に向けて学習中
Qiita:https://qiita.com/yuki4839
Twitter:https://twitter.com/yuki35522891

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

Let's EncryptでECDSAかつワイルドカードを含むサーバ証明書を発行する

前提条件

DNSサーバ(BIND9)が導入済み
その他のDNSサーバやRoute 53などは環境に応じて書き換えてください。

発行先のドメイン名が *.example.jp, example.jp
鍵生成アルゴリズムが ECDSA P_256
生成されるファイルは下記の通り

  • privkey.pem (秘密鍵)
  • cert.pem (サーバ証明書)
  • chain.pem (中間証明書)
  • fullchain.pem (サーバ証明書+中間証明書)
  • csr.pem (証明書署名要求)[中間ファイル]

検証環境

bash
$ uname -sr
Linux 4.18.0-193.6.3.el8_2.x86_64

$ cat /etc/redhat-release
CentOS Linux release 8.2.2004 (Core)

$ openssl version
OpenSSL 1.1.1c FIPS  28 May 2019

$ certbot --version
certbot 1.9.0

$ named -v
BIND 9.11.13-RedHat-9.11.13-6.el8_2.1

サーバ証明書生成スクリプトの作成

ユーザはroot、カレントディレクトリは/root/certで作業していきます。

1. メインのスクリプト

/root/cert/update-cert.sh
#!/bin/bash

# ECDSAで秘密鍵を生成する
# -out に出力される秘密鍵のファイル名 今回は「privkey.pem」
openssl ecparam \
    -genkey \
    -name prime256v1 \
    -out privkey.pem

# 証明書署名要求(CSR)を生成する
# -key にひとつ前で指定した秘密鍵のファイル名
# -subj に完全修飾ドメイン名(FQDN) 今回は「*.example.jp」 詳しくは少し下の'補足1'を参照
# -out に出力されるCSRのファイル名
openssl req \
    -new \
    -config openssl.cnf \
    -key privkey.pem \
    -subj '/CN=*.example.jp' \
    -out csr.pem

# 公開鍵に署名してもらう (公開鍵はひとつ前のコマンドでCSRに格納されています)
# -m にメールアドレス
# -d にFQDN 今回は「*.example.jpとexample.jp」 詳しくは少し下の'補足2'を参照
# --csr にひとつ前で指定したCSRのファイル名
# --manual-auth-hook にトークンをDNSに追加するスクリプト
# --manual-cleanup-hook にトークンをDNSから削除するスクリプト
certbot certonly \
    -n \
    --manual \
    --agree-tos \
    --manual-public-ip-logging-ok \
    -m 'admin@example.jp' \
    -d '*.example.jp' \
    -d 'example.jp' \
    --preferred-challenges=dns \
    --csr csr.pem \
    --manual-auth-hook ./dns-auth.sh \
    --manual-cleanup-hook ./dns-cleanup.sh

# サーバ証明書をリネームする
# この場合、実行時の日付ディレクトリに生成物が移動されます
DESTDIR=$(date +'%F')
mkdir $DESTDIR
mv privkey.pem $DESTDIR/
mv 0000_cert.pem $DESTDIR/cert.pem
mv 0000_chain.pem $DESTDIR/chain.pem
mv 0001_chain.pem $DESTDIR/fullchain.pem

メインのスクリプトはここまでです。
まだ実行しても正常に動作しません。


補足1 サブジェクトのコモンネーム
Qiitaの場合赤線で示されている部分
サーバ証明書 サブジェクトのコモンネーム


Qiitaの場合赤線で示されている部分
https://qiita.com/https://jobs.qiita.com/を1枚の証明書で済ませられます。
補足2 サブジェクト代替名
サーバ証明書 サブジェクト代替名

2. opensslのコンフィグ

openssl.cnfを作成します。
コピペして末尾2行を書き換えてください。

今回は最小限の設定しませんが、コピー元は/etc/pki/tls/openssl.cnfにあります。

/root/cert/openssl.cnf
[ req ]
default_md              = sha256
distinguished_name      = req_distinguished_name
string_mask             = utf8only
req_extensions          = v3_req

# サブジェクトの初期値を設定
# opensslコマンドの-subjオプションで指定しているため空欄のままで大丈夫です
[ req_distinguished_name ]
commonName_default      =

[ v3_req ]
basicConstraints        = CA:FALSE
keyUsage                = nonRepudiation,digitalSignature,keyEncipherment
subjectAltName          = @alt_names

# 以下のFQDNは任意のものに置き換えてください 今回は「*.example.jpとexample.jp」
[ alt_names ]
DNS.1   = *.example.jp
DNS.2   = example.jp

3. DNSSECの鍵を生成

nsupdateコマンドを使用してトークンをDNSサーバのレコードに追加、削除するための鍵ペアを生成します。

bash
# # -n HOST に任意の名前 今回は「_acme-challenge.example.jp」
# # ドメイン名にするのが無難です

# dnssec-keygen -r /dev/urandom -a HMAC-SHA256 -b 128 -n HOST _acme-challenge.example.jp
K_acme-challenge.example.jp.+163+25871


# # 実行すると2種類のファイルが生成されます。
# # [出力された文字列].key と [出力された文字列].private

# ls | grep _acme-challenge.example.jp
K_acme-challenge.example.jp.+163+25871.key
K_acme-challenge.example.jp.+163+25871.private

4. トークンをDNSサーバのレコードに追加するスクリプト

dns-01認証で発行されるトークンをDNSサーバのレコードに追加する処理を書きます。
BINDの場合はnsupdateコマンドを使用しますが、Route 53などは環境に応じた処理に置き換えてください。
Cloudflare DNSのサンプルはCertbotのドキュメント1にあります。

/root/cert/dns-auth.sh
#!/bin/bash

# -k に項番号3で生成されたファイル名 今回は「K_acme-challenge.example.jp.+163+25871.private」
# server に更新するのDNSサーバのIPアドレスまたはドメイン名 今回は「ns1.example.jp」
# update に更新する処理 ドメイン名は環境に応じて置き換えてください。
# ドメイン名の最後に「.」を忘れずに入れてください。 今回は「_acme-challenge.example.jp.」
# $CERTBOT_VALIDATIONにトークンが代入されています。
cat << EOF | nsupdate -k 'K_acme-challenge.example.jp.+163+25871.private'
server ns1.example.jp
update add _acme-challenge.example.jp. 3600 TXT $CERTBOT_VALIDATION
send
EOF

# 反映されるまで適当に待つ
sleep 30

5. トークンをDNSサーバのレコードから削除するスクリプト

dns-01認証終了後にDNSサーバからレコードを削除する処理を書きます。
項番号4と同様に環境に応じて置き換えてください。

/root/cert/dns-cleanup.sh
#!/bin/bash

# 項番号4のコメントに同じ
cat << EOF | nsupdate -k 'K_acme-challenge.example.jp.+163+25871.private'
server ns1.example.jp
update delete _acme-challenge.example.jp.
send
EOF

DNSサーバの設定

nsupdateコマンドを受け入れるようにDNSサーバの設定を変更します。

bash
# # サーバ証明書生成スクリプトの作成の項番号3で生成されたファイルを開いて
# # Key の値をコピーします 今回は「thisISdnsSECexampleKEY==」
# cat K_acme-challenge.example.jp.+163+25871.private
Private-key-format: v1.3
Algorithm: 163 (HMAC_SHA256)
Key: thisISdnsSECexampleKEY==
Bits: AAA=
Created: 20201119190706
Publish: 20201119190706
Activate: 20201119190706

以下、DNSサーバ

/etc/named.conf
# named.conf にDNSSECの鍵を追記する
# key に項番号3で指定した値 今回は「_acme-challenge.example.jp.」
# 項番号3で指定した値が含まれていないとエラーになるみたいです
# secret にひとつ前でコピーしたKey 今回は「thisISdnsSECexampleKEY==」
key "_acme-challenge.example.jp." {
    algorithm    hmac-sha256;
    secret       "thisISdnsSECexampleKEY==";
};
/etc/named/example.jp.conf
# ドメインの更新を許可する
# key にひとつ前で設定した名前を指定する 今回は「_acme-challenge.example.jp.」
zone "example.jp" {
    type    master;
    # ...(省略)...
    allow-update { key _acme-challenge.example.jp.;
}

基本的なDNSサーバの設定は他のサイトを参考にしてください。

テスト

サーバ証明書を発行する前にDNS-01認証のテストを行います。
cert-update.sh--dry-runのオプションを追加して一度実行します。

/root/cert/update-cert.sh
# ...省略...
# certbotコマンドの末尾に--dry-runを追記します
certbot certonly \
    -n \
    --manual \
    --agree-tos \
    --manual-public-ip-logging-ok \
    -m 'admin@example.jp' \
    -d '*.example.jp' \
    -d 'example.jp' \
    --preferred-challenges=dns \
    --csr csr.pem \
    --manual-auth-hook ./dns-auth.sh \
    --manual-cleanup-hook ./dns-cleanup.sh
    --dry-run
    # ↑ 追記
# ...省略...

実行後に以下のように表示されればテストは成功です。

bash
# ./update-cert
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Performing the following challenges:
dns-01 challenge for example.jp
dns-01 challenge for example.jp
Running manual-auth-hook command: ./dns-auth.sh
Running manual-auth-hook command: ./dns-auth.sh
Waiting for verification...
Cleaning up challenges
Running manual-cleanup-hook command: ./dns-cleanup.sh
Running manual-cleanup-hook command: ./dns-cleanup.sh

IMPORTANT NOTES:
 - The dry run was successful.
mv: '0000_cert.pem' を stat できません: そのようなファイルやディレクトリはありません
mv: '0000_chain.pem' を stat できません: そのようなファイルやディレクトリはありません
mv: '0001_chain.pem' を stat できません: そのようなファイルやディレクトリはありません

The dry run was successful.と表示されなかった場合はエラーの内容から該当箇所を修正してください。
--dry-runオプションはサーバ証明書が発行されないためmvコマンドでエラーが表示されています。

テストに成功したら--dry-runオプションを外して実行します。
update-cert.shにサーバ証明書のシンボリックリンクを張る処理やサービス再起動の処理を追記してもいいと思います。

cronの設定

ここまで実装したらスクリプトの実行も自動化します。
サーバ証明書の有効期限が3ヶ月のため2ヶ月に1度サーバ証明書を更新します。
下記の例は2,4,6,8,10,12月の18日午前3時36分に更新されます。
認証サーバが混み合わないように0時0分などを避けて適当な日時にしておきます。
出力を/dev/nullに捨てるのはやめましょう。

# crontab -e
36 3 18 2,4,6,8,10,12 * /root/cert/update-cert.sh >> /var/log/update-cert.log

参考サイト

User Guide — Certbot 1.10.0.dev0 documentation
Bind9でDynamicDNSを構築 - K'z Arch@K'z Style(ケイズ・スタイル)


  1. User Guide — Certbot 1.10.0.dev0 documentationのPre and Post Validation Hooks項 

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