- 投稿日:2020-04-14T21:51:52+09:00
AWS ClientVPNのおかげで、3日で3000名分のリモートワーク環境を構築できた話
はじめに
表題の件で、備忘録としてダラダラと書き連ねます。
※Qiita初投稿です。実際にやってみるとアウトプットって難しいですね(今までお世話になったQiita記事の投稿者の皆様に改めて感謝です…)背景
- 新型コロナウイルス感染症にかかる緊急事態宣言を受けて、4/8(水)から弊社でも在宅勤務がスタート
- 社員数4000名以上の弊社で準備していた既存VPNは、同時接続数がわずか1000
- 在宅勤務開始直後から「VPN接続できない!」というクレームの嵐
- NWベンダに確認したところ、現VPNは同時接続数1000ではなく、同時セッション数1000だったと判明し絶望
- 4/9(木) 対応策検討開始。お上から「週明けには解決しろ!」
- 「AWS ClientVPN」を発見。万年人手不足の情シスに嬉しいマネージドのVPN?激アツじゃないですか
ゴール
VPN接続したユーザが、DX経由で社内リソースやインターネット/各種Saasへアクセスできる状態を目指します
※「全通信、社内経由とかイケてないww」「この機会にゼロトラスト進めろよw」と思われるでしょう。社内理解を得る難しさと、リードタイムなど考慮すると、選択肢が限られていたのです…0. 前提条件
0-1. お金の確保
今回の構成において、課金対象となるのは下記のリソースです(2020年4月時点@東京リージョン)
課金対象リソース 料金 課金単位 補足 AWS ClinetVPN endpoint association $0.15 1時間毎 エンドポイントとサブネットの関連付に対して課金 AWS ClinetVPN endpoint connection $0.05 1時間毎 アクティブなVPN接続に対して課金 AD Connector(Large) $0.24 1時間毎 ディレクトリ認証を利用するため DirectConnect(Outbound) $0.041 1GB毎 DX→DCのデータ転送 3000ユーザ※が毎日7.5時間、20営業日利用するケースを想定し、ざっくり費用を算出しました。
計算すれば分かりますが、決して安い金額にはなりません。しかし、初期費用不要/週明けには展開可ということで、緊急対応策として承認もらえました。
※社員数4000名以上なのに3000?…諸事情で全員が在宅勤務できるわけではないため一旦3000でよいとのこと0-2. AWS環境(DirectConnectあり)
技術的には、インターネット経由で社内リソースへアクセスさせることも可能ですが、セキュリティ意識の高いお上の了承を得るのが難しい可能性があります。幸い、弊社ではDirectConnectでDCと専用線接続している AWS環境が整っていました。
0-3. 制限緩和
- 他のAWSサービス同様、ClientVPNにも各種制限があります。 弊社の場合3000ユーザ想定のため、「エンドポイントあたりの同時クライアント接続数:2000」の制限緩和をリクエストしました。複数のエンドポイントで構成するなら緩和不要ですが、エンドポイント毎に接続先URLが異なると、エンドユーザへの展開が複雑になります。
- 通常、制限緩和は「Service Limit Increase」の方からリクエストしますが、現時点では当該項目が見当たらなかったため「Technical Support」から起票
- 申請の理由や背景、過去のClientVPN利用実績、なぜ複数のエンドポイント構成だと厳しいのか等、詳しい説明が必要です。最終的にはUS側の判断となるため返信を待ちます。24時頃に起票し、翌日夕方には制限緩和承認の連絡を受領しました
1. 構築編
1-1. AD Connectorの作成
ClientVPNはディレクトリ認証/相互認証を利用できますが、今回の構成はどちらも利用します。前者のため、AD Connectorを作成します。
作成手順は長くなるのでコチラをご覧ください
1-2. ClientVPNエンドポイント用セキュリティグループの作成
ClinetVPNエンドポイントを作成すると、関連付けされたサブネット上にENIが自動的に作られます。このENIに適用するセキュリティグループを作成します。
AWSコンソールにて「VPC」→「セキュリティグループ」→「セキュリティグループの作成」
名前と説明を入力、VPCを指定し、「作成」をクリック
1-3. CloudWatchロググループ作成
クライアント接続の記録を保管するためのロググループを作成します。
AWSコンソール→「CloudWatch」→「ロググループ」で「ロググループの作成」をクリック
ロググループ名を入力し、「作成」をクリック
作成完了
1-4. サーバ/クライアント証明書作成、ACMへの証明書登録
相互認証のため、公式ドキュメントに従って証明書を作成し、AWS Certificate Manager(ACM)へアップロードします。
1-5. ClientVPNエンドポイントの作成
いよいよ本題です。AWSコンソール→「VPC」→「クライアント VPN エンドポイント」に進み、「クライアント VPN エンドポイントの作成」をクリック
必要項目を記入します。
「クライアント IPv4 CIDR」→接続するクライアントに割り当てるIP(/22以上必須)。社内/AWSリソースのIPと重複しないように注意です。※作成後変更不可
「サーバ証明書ARN」「クライアント証明書ARN」では、1-4で登録した証明書を選択
「認証オプション」は全て選択
「DNSサーバ~」に、社内DNSサーバのIPを入力
「セキュリティグループID」に、1-2で作成したセキュリティグループを選択
1-6. ClientVPNエンドポイントについて、サブネット関連付
作成したエンドポイントを選択し、「関連付け」タブの「関連付け」をクリック
対象のVPCと、関連付けるプライベートサブネットを指定し、「関連付け」をクリック
※可用性確保のため、複数のサブネットを関連付けする場合は1-6を再度実施
1-7. 認証ルールの追加
誰がどこにアクセスするかを制御する、つまり認可の制御を担うのが「認証ルール」となります。
まず、作成したエンドポイントを選択し、「受信の承認」タブの「受信の承認」をクリック
要件に応じて記入し「認証ルールの追加」をクリック
- 弊社の場合、要件は「取り急ぎ社員は全てアクセス許可でよいが、社外ベンダは指定のリソースのみに限定したい」
- ユーザはADグループで管理しているため、「アクセスを付与する対象」として「特定の~」を選び、ADグループのSIDを指定
- 「送信先ネット」欄にアクセスできるIPアドレス範囲を記入
完了(しばらく待って、状態が「アクティブ」になることを確認)
1-8. クライアント設定のダウンロードと編集
あと少しです。エンドポイントを選択→「クライアントの設定のダウンロード」→「ダウンロード」をクリック
ダウンロードしたovpnファイルを開き、ファイル末尾にクライアント証明書と秘密鍵の内容をコピペします(※パス指定してもOK)
1-9. 確認
- OpenVPNをインストール(AWS公式のクライアントもありますが、動作不安定と聞いたのでパス)
- OpenVPNのconfigフォルダ(C:\Program Files\OpenVPN\config)に、1-8で作成したovpnファイルを格納
- OpenVPN起動
- タスクトレイ→「OpenVPN」メニュ→「接続」
- ディレクトリ認証画面にて、ADユーザ名・パスワード入力し「OK」
接続成功!(社内リソースへのアクセスや、IP縛りしてるSaasへのログインも成功)
2. 検証編
上記の通り、手順はシンプルなので半日で構築完了(マネージドって素晴らしいですね…!)。しかし、動作検証の中で下記問題が発生し、土曜日がつぶれました…。
2-1. 問題:Outlookの認証失敗
時折、Outookクライアントにおいて下記エラーが表示され、全く送受信できなくなるという現象が発生。
2-2. 原因/対応策
- 該当エラーに関する記事がありました→「インターネット接続性チェックが失敗する環境で Outlook 2013/2016 による先進認証が失敗する」
- Win10 にはNetwork Connection Status Indicator(NCSI)という機能があり、ネットワークの接続が変わったタイミング(無線LANにつなぐとか,VPNにつなぐとか)で、特定のURLに接続し、インターネット接続を確認するそうです(初めて知りました…)。Outlookで先進認証をする際も、NCSIで接続性を確認しており、インターネット接続がないと判断されると、Outlook でエラーが出るそうです
- 調べているうちに、OpenVPNで接続確立後のルートテーブルを見ると、デフォルトルート 0.0.0.0 に対して、VPNクライアントのインターフェースのメトリックの値が大きい=優先度が低くなっていることに気づきます。「ルート追加時にメトリックを指定する方法」を参考に、ovpnファイルに
route 0.0.0.0 0.0.0.0 vpn_gateway 0
を追記することで、デフォルトゲートウェイを追加でき、エラーは解消しました。3. 運用編
各種エラーをつぶし、まともに使えるレベルになりました。日曜日一日かけて、下記を実施しました。
3-1. ユーザへの提供準備
- テストユーザ増やして、動作検証
- OpenVPNインストーラ/ovpnファイルをユーザに配信できるよう、IT資産管理ソフト設定
- ユーザ向けインストール/初期設定マニュアルの作成
3-2. 監視環境の整備
3-2-1. 課金状況の監視
「使いすぎは避けて」「Web会議するときはVPN切断を」と案内したものの、(情シスの方なら分かっていただけると思いますが)ユーザがどんな使い方をするか分かりません。Cost Explorerで課金対象項目を指定したレポートを作成しました
3-2-2. 利用状況の監視
ClientVPNエンドポイントについて、CloudWatchで下記のメトリクスを取得可能です(参考)
- 送信バイト
- 送信パケット
- 受信バイト
- 受信パケット
- 認証の失敗 (カウント)
- アクティブ接続 (カウント)当初、CloudWatchダッシュボードをサクッと作る予定でしたが、Grafanaでダッシュボードを作成し、社内全員に公開することにしました。(逐一状況を把握したいお上の要望に応えると同時に、ユーザにも状況をシェアすることで、皆に考えながら使ってもらいたいよねという意見があったため)
※初めてGrafana触りましたが、便利ですね。参考にした記事は↓
- Grafanaでかっけぇダッシュボード作るよ!(構築・設定編)
- 今回作成したClientVPNエンドポイントと同じ、プライベートサブネット上でEC2(t2.micro)で動いてます。メトリクス取得するため、VPCエンドポイント作成も必要終わりに
週明けからユーザへの提供開始。ユーザからは次々と好評の声が寄せられてますが、利用ユーザ数が増えるとどうなるか未知のため、戦々恐々と監視画面を見つめています。
一息ついたところで、上司がポロリ「でも、上からは『こんなに簡単にできるなら、なぜもっと早くやってなかったんだ』と怒られるかもな…」
…情シスの悲しい現実ですね。
管理面での課題もあるため、今後随時改善していく予定です。最後まで読んで頂きありがとうございました。
- 投稿日:2020-04-14T21:39:19+09:00
【試験合格記】AWS 認定 機械学習 – 専門知識(MLS-C01)
お疲れさまです。
表題の試験に合格したため記録として残したいと思います。結果
合格(902点)
分野 名称 割合 1 データエンジニアリング 20% 2 探索的データ解析 24% 3 モデリング 36% 4 機械学習の実装と運用 20% 所有資格
資格名 取得年月日 AWS Certified Solutions Architect - Associate (SAA) 2018-06-14 AWS Certified SysOps Administrator - Associate (SOA) 2018-06-22 AWS Certified Developer - Associate (DVA) 2018-06-25 AWS Certified Solutions Architect - Professional (SAP) 2018-07-19 AWS Certified DevOps Engineer - Professional (DOP) 2020-02-19 AWS Certified Big Data - Speciality (BDS) 2020-03-23 AWS Certified Security - Speciality (SCS) 2020-04-01 AWS Certified Machine Learning - Speciality (MLS) 2020-04-13 事前知識
機械学習にガッツリ取り組んだ経験はありません。
GCPのデータエンジニア試験を受けた際に機械学習に関する一般的な知識は重点的に学んだ経験があります。所感
他の方の合格記事を見られた方はなんとなく理解されてると思いますが、出題範囲はほぼ機械学習モデルとSageMakerに集中しています。
ですので、この領域が完全に未経験の場合は回帰や分類、教師ありなし学習などがどのような意味か、というところから書籍などで理解する必要があります。
一部、データレイクやETL周りのアーキテクチャも出題されますが、これはSAPやDOPを取得していれば理屈で答えられると思います。受験者に向けたアドバイス
- 予測や分類、アルゴリズムやハイパーパラメータなどは幅広く固有名詞とどういうパターンに当てはまるか整理する
- 正規化、非正規化、トレーニングセットやテストセットの精度に異常がある場合の改善方法を理解する
- SageMakerと親和性の高いAWSサービスの理解と組み合わせ方を学ぶ
- ノートブックインスタンスの特徴を把握しておく
- Transcribe、Comprehend、Translate、Polly、Lexなどの機械学習関連サービスの特徴を理解する
- KinesisとGlueの使い方を理解する
まとめ
これで専門知識資格を3つ取得できました。
月内にネットワークを受けられればいいなと思いながら地道に試験対策を進めていこうと思います。
あとはこの試験について学習したことで機械学習の具体的な使い方やワークフローについて理解できたので社内データをなんとか活用したいというモチベーションが上がったことが収穫でした。
- 投稿日:2020-04-14T20:04:57+09:00
AWS 課金回避方法
AWS無料期間について
AWSのアカウントを作成してから12ヶ月間、以下のアプリケーションは無料で利用できます。
※12ヶ月が過ぎてしまうと課金が始まってしまうので注意が必要。
Amazon EC2
750時間/月 (t2.microインスタンスの使用もこれに含む)まで
Amazon S3:
5GBの標準ストレージ、20,000件のGETリクエスト、2,000件のPUTリクエスト
Elastic IPアドレス
実行中のインスタンスに関連づけられたElastic IPアドレスを1つだけ
インスタンスに紐付いていないElastic IPアドレスは全て課金対象
IAM
IAMユーザーの一時的なセキュリティ認証情報を使用して他のAWSサービスにアクセスするときのみ料金が発生2つ目以降のインスタンスを作成する際の課金回避法
インスタンスを作成し直す際や、別のアプリケーションをデプロイするためには別インスタンスを立ち上げることになります。以下の手順を踏めば課金は解除できるでしょう。
手順
1.Elastic IPアドレスを解放する
2.(すでに作成済みで、これ以上必要の無い場合)紐付いているS3バケットを削除する
3.インスタンスを削除する1.Elastic IPアドレスを解放する
1.AWSアカウントのルートユーザーにログインする
※IMAユーザーの場合、以下のようなエラーが出ると思います。
2.Amazon EC2 コンソールを開く
3.Elastic IP アドレスを選択し、[Actions]、[Release addresses] の順に選択します。
※もし、解放ができない場合は、アドレスの関連付けの解除を押してからアドレスの解放を押してください。
以上で、1.Elastic IPアドレスを解放は完了です。2.(すでに作成済みで、これ以上必要の無い場合)紐付いているS3バケットを削除する
1.AWS マネジメントコンソールにサインインし、Amazon S3 コンソールを開きます。
2.[バケット名] リストで、削除するバケットの名前の横にあるバケットアイコンを選択し、[バケットを削除する] を選択します。※バケットにオブジェクトが含まれている場合は、[This bucket is not empty (このバケットは空ではありません)] というエラーアラートの [バケットを空にする設定] リンクを選択し、[バケットを空にする] ページの指示に従って、バケットを空にしてから削除します。次に、[バケットを削除する] ページに戻り、バケットを削除します。
以下のような状態になれば2.に戻って削除に入ります。
3.[バケットを削除する] ダイアログボックスで、削除するバケットの名前を確認のために入力し、[確認] を選択します。3.インスタンスを削除する
インスタンスを停止するとEIastic IPアドレスは関連づけられなくなるので、あらかじめEIastic IPアドレスを解放し課金されないように気をつけましょう。
1.ナビゲーションペインで [Instances] を選択し、インスタンスを選択します。2.[Actions] を選択して [Instance State] を選択し、[Stop] を選択します。
[Stop] が無効になっている場合は、インスタンスが既に停止しているか、またはルートボリュームがインスタンスストアボリュームです。(インスタンスを停止すると、インスタンスストアボリューム上のデータは消去されます。インスタンスストアボリュームのデータを保持するには、このデータを永続的ストレージに必ずバックアップしてください。)
停止、終了など選択できると思うので削除したい場合は終了を押してください
停止の場合はEIastic IP(住所のようなもの)を削除していないと課金が発生してしまいます。3.確認ダイアログボックスで [Yes, Stop] を選択します。
※インスタンスが停止するまで、数分かかる場合があります。
- 投稿日:2020-04-14T18:23:50+09:00
【GitHub Actions】俺はactions/cacheをやめるぞ!S3ィィィィィッ!!
はじめに
GitHub Actions公式のキャッシュ機能である
actions/cache
は、
- Pull Requestでコケた時にRe-run jobsするとactions/cacheアクションが正常に動作しない
- actions/cacheアクションは時折キャッシュの取得に失敗することがある
などの問題を抱えているようです。
詳しくは、こちらのブログ記事を参照ください。
加えて、キャッシュの容量はリポジトリごとに5GBとのことなのですが、明らかに容量オーバーしていないのに、いつのまにかキャッシュが追い出されていることがあるような気がします(検証はして無いので、私の思い込みかもしれません)。
そこで、
actions/cache
を使わず、S3に独自にキャッシュさせることにしました。今のところ、快適に動いているので、今回その内容を紹介させていただきます。
S3に独自にキャッシュするためにやったこと
- S3バケットの作成
- IAMユーザーの作成
- GitHubリポジトリへのSecretsの設定
- ワークフローの修正とシェルスクリプトの作成
1. S3バケットの作成
まず、S3バケットを作成してください。
パブリックアクセスをすべてブロック
をオンにするなど、標準の設定で問題ありません。GitHub Actionsの実行環境は、Azureの米国のリージョンにあるそうなので、S3バケットは近そうな
us-east-1
に作ることにしました。WindowsとUbuntuのランナーはAzureでホストされ、IPアドレスの範囲がAzureデータセンターと同じになります。 現在、すべてのWindows及びUbuntuのGitHubホストランナーは、以下のAzureリージョン内にあります。
米国東部(eastus)
米国東部2 (eastus2)
米国西部2 (westus2)
米国中部 (centralus)
米国中南部(southcentralus)なお、適当な期間を過ぎたらキャッシュが削除されるよう、ライフサイクルルールも作っておくと良いと思います。
2. IAMユーザーの作成
S3とキャッシュをやり取りするためのIAMユーザーを作成します。
S3に対して、以下のような操作を許可するようポリシーを与えます。
IAMユーザーのポリシー{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::aws-us-east-1-xxxxxxxxxxxx-github-actions-caches/*", "arn:aws:s3:::aws-us-east-1-xxxxxxxxxxxx-github-actions-caches" ] } ] }また、アクセスキーを作成し、アクセスキーIDとシークレットアクセスキーを控えてください。
後で、GitHubのSecretsに設定します。
3. GitHubリポジトリのSecretsへの設定
先ほどのアクセスキーIDとシークレットアクセスキーをそれぞれGitHubのリポジトリのSecretsに設定します。
4. ワークフローの修正とシェルスクリプトの作成
コメントアウトしている箇所は、
actions/cache
を使っている場合のワークフローです。4.1. composerの例
.github/workflows/build_test.yml# - name: cache composer # id: cache-composer # uses: actions/cache@v1.1.2 # with: # path: laravel/vendor # key: composer-v1-${{ hashFiles('laravel/composer.lock') }} # - name: composer install # if: steps.cache-composer.outputs.cache-hit != 'true' # run: composer install -n --prefer-dist # working-directory: laravel - name: composer install env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_CACHE_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_CACHE_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: ap-northeast-1 # aws cliを使う上でのデフォルトリージョン AWS_S3_BUCKET: aws-us-east-1-847754820862-github-actions-caches CACHE_KEY: composer-v1-${{ hashFiles('laravel/composer.lock') }} PATHS: vendor # EXEC_DIRを起点としたパス BUILD_COMMAND: composer install -n --prefer-dist EXEC_DIR: laravel # zipやBUILD_COMMANDを実行するディレクトリ run: .github/workflows/cache.sh4.2. npmの例
.github/workflows/build_test.yml# - name: cache npm # id: cache-npm # uses: actions/cache@v1.1.2 # with: # path: laravel/node_modules # key: npm-v1-${{ hashFiles('laravel/package-lock.json') }} # - name: npm ci if there are no node_modules # if: steps.cache-npm.outputs.cache-hit != 'true' # run: npm ci # working-directory: laravel - name: npm ci env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_CACHE_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_CACHE_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: ap-northeast-1 # aws cliを使う上でのデフォルトリージョン AWS_S3_BUCKET: aws-us-east-1-xxxxxxxxxx-github-actions-caches CACHE_KEY: npm-v1-${{ hashFiles('laravel/package-lock.json') }} PATHS: node_modules # EXEC_DIRを起点としたパス BUILD_COMMAND: npm ci EXEC_DIR: laravel # zipやBUILD_COMMANDを実行するディレクトリ run: .github/workflows/cache.shなお、キャッシュとして保存したいディレクトリやファイルが複数ある場合は、
PATHS
にスペース区切りで記述してください。4.3. シェルスクリプト
ひとつのシェル内で、
- キャッシュがS3にあればダウンロード
- キャッシュが無ければ、パッケージをインストールしてS3にキャッシュとしてアップロード
を行います。
.github/workflows/cache.sh#!/bin/bash set -eu cd ${GITHUB_WORKSPACE}/${EXEC_DIR} FILE=${CACHE_KEY}.zip CACHE_HIT=`aws s3 ls s3://${AWS_S3_BUCKET}/${FILE}` || true if [ -n "$CACHE_HIT" ]; then echo "Found a cache for key: ${FILE}" aws s3 cp s3://${AWS_S3_BUCKET}/${FILE} ./ unzip -n $FILE echo "Done is unzip -n ${FILE}" rm -f $FILE echo "Done is rm -f ${FILE}" else echo "No cache is found for key: ${FILE}" $BUILD_COMMAND zip -ryq $FILE $PATHS echo "Done is zip -ryq ${FILE} ${PATHS}" aws s3 cp $FILE s3://${AWS_S3_BUCKET}/ echo "Stored cache to ${FILE}" fi実際に使ってみて
正確に測っていませんが、速度的には
actions/cache
と遜色無い気がします。何より、キャッシュがそこにあるはずなのにヒットしない、という状況にもやもやすることが無いのは快適でした。
また、
actions/cache
は、
- キャッシュをリストアしたいタイミングに使用するステップを記述するのみとなり、保存のステップは記述しない。キャッシュの保存は、
actions/cache
のステップが存在するジョブの最後にPost + actions/cache
のステップ名というステップ名で実行される。という仕様となっており、ジョブが正常終了しなかった場合は、キャッシュを保存するステップは実行されません。
今回の自家製シェルはパッケージのインストール後に必ずキャッシュを保存するので、その点で無駄が少ないのでは、と思っています。
- 投稿日:2020-04-14T18:23:50+09:00
【GitHub Actions】「俺はactions/cacheをやめるぞ!」「S3ィィィィィッ!!」
はじめに
GitHub Actions公式のキャッシュ機能である
actions/cache
は、
- Pull Requestでコケた時にRe-run jobsするとactions/cacheアクションが正常に動作しない
- actions/cacheアクションは時折キャッシュの取得に失敗することがある
などの問題を抱えているようです。
詳しくは、こちらのブログ記事を参照ください。
加えて、キャッシュの容量はリポジトリごとに5GBとのことなのですが、明らかに容量オーバーしていないのに、いつのまにかキャッシュが追い出されていることがあるような気がします(検証はして無いので、私の思い込みかもしれません)。
そこで、
actions/cache
を使わず、S3に独自にキャッシュさせることにしました。今のところ、快適に動いているので、今回その内容を紹介させていただきます。
S3に独自にキャッシュするためにやったこと
- S3バケットの作成
- IAMユーザーの作成
- GitHubリポジトリへのSecretsの設定
- ワークフローの修正とシェルスクリプトの作成
1. S3バケットの作成
まず、S3バケットを作成してください。
パブリックアクセスをすべてブロック
をオンにするなど、標準の設定で問題ありません。GitHub Actionsの実行環境は、Azureの米国のリージョンにあるそうなので、S3バケットは近そうな
us-east-1
に作ることにしました。WindowsとUbuntuのランナーはAzureでホストされ、IPアドレスの範囲がAzureデータセンターと同じになります。 現在、すべてのWindows及びUbuntuのGitHubホストランナーは、以下のAzureリージョン内にあります。
米国東部(eastus)
米国東部2 (eastus2)
米国西部2 (westus2)
米国中部 (centralus)
米国中南部(southcentralus)なお、適当な期間を過ぎたらキャッシュが削除されるよう、ライフサイクルルールも作っておくと良いと思います。
2. IAMユーザーの作成
S3とキャッシュをやり取りするためのIAMユーザーを作成します。
S3に対して、以下のような操作を許可するようポリシーを与えます。
IAMユーザーのポリシー{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::aws-us-east-1-xxxxxxxxxxxx-github-actions-caches/*", "arn:aws:s3:::aws-us-east-1-xxxxxxxxxxxx-github-actions-caches" ] } ] }また、アクセスキーを作成し、アクセスキーIDとシークレットアクセスキーを控えてください。
後で、GitHubのSecretsに設定します。
3. GitHubリポジトリのSecretsへの設定
先ほどのアクセスキーIDとシークレットアクセスキーをそれぞれGitHubのリポジトリのSecretsに設定します。
4. ワークフローの修正とシェルスクリプトの作成
コメントアウトしている箇所は、
actions/cache
を使っている場合のワークフローです。4.1. composerの例
.github/workflows/build_test.yml# - name: cache composer # id: cache-composer # uses: actions/cache@v1.1.2 # with: # path: laravel/vendor # key: composer-v1-${{ hashFiles('laravel/composer.lock') }} # - name: composer install # if: steps.cache-composer.outputs.cache-hit != 'true' # run: composer install -n --prefer-dist # working-directory: laravel - name: composer install env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_CACHE_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_CACHE_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: ap-northeast-1 # aws cliを使う上でのデフォルトリージョン AWS_S3_BUCKET: aws-us-east-1-847754820862-github-actions-caches CACHE_KEY: composer-v1-${{ hashFiles('laravel/composer.lock') }} PATHS: vendor # EXEC_DIRを起点としたパス BUILD_COMMAND: composer install -n --prefer-dist EXEC_DIR: laravel # zipやBUILD_COMMANDを実行するディレクトリ run: .github/workflows/cache.sh4.2. npmの例
.github/workflows/build_test.yml# - name: cache npm # id: cache-npm # uses: actions/cache@v1.1.2 # with: # path: laravel/node_modules # key: npm-v1-${{ hashFiles('laravel/package-lock.json') }} # - name: npm ci if there are no node_modules # if: steps.cache-npm.outputs.cache-hit != 'true' # run: npm ci # working-directory: laravel - name: npm ci env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_CACHE_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_CACHE_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: ap-northeast-1 # aws cliを使う上でのデフォルトリージョン AWS_S3_BUCKET: aws-us-east-1-xxxxxxxxxx-github-actions-caches CACHE_KEY: npm-v1-${{ hashFiles('laravel/package-lock.json') }} PATHS: node_modules # EXEC_DIRを起点としたパス BUILD_COMMAND: npm ci EXEC_DIR: laravel # zipやBUILD_COMMANDを実行するディレクトリ run: .github/workflows/cache.shなお、キャッシュとして保存したいディレクトリやファイルが複数ある場合は、
PATHS
にスペース区切りで記述してください。4.3. シェルスクリプト
ひとつのシェル内で、
- キャッシュがS3にあればダウンロード
- キャッシュが無ければ、パッケージをインストールしてS3にキャッシュとしてアップロード
を行います。
.github/workflows/cache.sh#!/bin/bash set -eu cd ${GITHUB_WORKSPACE}/${EXEC_DIR} FILE=${CACHE_KEY}.zip CACHE_HIT=`aws s3 ls s3://${AWS_S3_BUCKET}/${FILE}` || true if [ -n "$CACHE_HIT" ]; then echo "Found a cache for key: ${FILE}" aws s3 cp s3://${AWS_S3_BUCKET}/${FILE} ./ unzip -n $FILE echo "Done is unzip -n ${FILE}" rm -f $FILE echo "Done is rm -f ${FILE}" else echo "No cache is found for key: ${FILE}" $BUILD_COMMAND zip -ryq $FILE $PATHS echo "Done is zip -ryq ${FILE} ${PATHS}" aws s3 cp $FILE s3://${AWS_S3_BUCKET}/ echo "Stored cache to ${FILE}" fi実際に使ってみて
正確に測っていませんが、速度的には
actions/cache
と遜色無い気がします。何より、キャッシュがそこにあるはずなのにヒットしない、という状況にもやもやすることが無いのは快適でした。
また、
actions/cache
は、
- キャッシュをリストアしたいタイミングに使用するステップを記述するのみとなり、保存のステップは記述しない。キャッシュの保存は、
actions/cache
のステップが存在するジョブの最後にPost + actions/cache
というステップ名で実行される。という仕様となっており、ジョブが正常終了しなかった場合は、キャッシュを保存するステップは実行されません。
今回の自家製シェルはパッケージのインストール後に必ずキャッシュを保存するので、その点で無駄が少ないのでは、と思っています。
- 投稿日:2020-04-14T16:09:02+09:00
EC2 EBS ボリューム拡張
手順メモ
EC2に接続されてるボリュームをAWS管理画面上から拡張
管理画面で実行
今回は8GB -> 30GB に拡張現状をdf
# df -h Filesystem Size Used Avail Use% Mounted on devtmpfs 992M 56K 992M 1% /dev tmpfs 1001M 0 1001M 0% /dev/shm /dev/xvda1 7.8G 7.5G 173M 98% /
lsblk で確認
# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT xvda 202:0 0 30G 0 disk └─xvda1 202:1 0 8G 0 part /
growpart実行
growpart - extend a partition in a partition table to fill available space
# growpart /dev/xvda 1 # growpart /dev/xvda 1 CHANGED: disk=/dev/xvda partition=1: start=4096 old: size=16773086,end=16777182 new: size=62910430,end=62914526resize2fs で拡張実行
# resize2fs /dev/xvda1 resize2fs 1.42.12 (29-Aug-2014) Filesystem at /dev/xvda1 is mounted on /; on-line resizing required old_desc_blocks = 1, new_desc_blocks = 2 The filesystem on /dev/xvda1 is now 7863803 (4k) blocks long.dfで確認
# df -h Filesystem Size Used Avail Use% Mounted on devtmpfs 992M 56K 992M 1% /dev tmpfs 1001M 0 1001M 0% /dev/shm /dev/xvda1 30G 7.5G 22G 26% /
完了
- 投稿日:2020-04-14T15:53:58+09:00
(編集中)API Gateway
- API Gatewayとは、Web API(HTTP/HTTPSベースで実現するAPI)の一種。
- リージョンレベルでデプロイされるサービス(S3と同じ)
- サーバレスアーキテクチャ(インフラ管理は不要)
- 呼び出し回数によって料金が発生
そもそもRESTとは
RESTとはRepresentational State Transferの略称で、下記のRESTの考え方に従って実装されたAPIをRESTful API(またはREST API)と呼ぶ。
- HTTPのメソッド(命令)でデータ操作種別(CRUD)を表す
- POSTメソッドであれば作成(Create)、GETメソッドであれば参照(Reference)、PUT/PATCHメソッドであれば更新(Update)、DELETEメソッドであれば削除(Delete)を表す ステートレスにする
- 前回のAPIコール結果にかかわらず同じ値を戻す。例えば合計1000件のデータが存在し、1回目のAPIコールで100件まで取得したとしても、その状態は考慮せず、2回目のAPIコールでも同じ100件を戻すという挙動だ
- URIで操作対象のリソースを判別可能にする
- RESTでは、APIを介して操作する対象を「リソース」と呼ぶ。例えば「ユーザー」というリソースを表すために「users」というリソース名を付与することがある。ユーザーIDが「1000」のユーザー情報を取得したい場合、下記のようなURIフォーマットでURIを生成し、操作可能とする
- レスポンスとしてXMLもしくはJSONで操作結果を戻す
- 適切にデータ操作できた場合、データ記述言語のXMLもしくはJSONでデータ操作結果を記述し、HTTPのレスポンスボディーに含め、APIコール元に戻す
Web APIが爆発的に広がるきっかけになったのがスマートフォンアプリではないかと思います。スマートフォンアプリはそれ単体で使われるものは多くなく、何らかの形でインターネット上のサーバとデータの送受信を行っています。そうした時にサーバ側はWeb APIを用意し、アプリからはWeb APIを呼び出します。一般的に外部の開発者に向けて公開されているものがWeb APIと思われますが、こういったそのアプリ向けだけの専用かつ非公開なWeb APIはとても数多く存在します。
開発基盤と問わずに実行
- 投稿日:2020-04-14T15:22:18+09:00
Amazon Translate、AWS Lambda を使った自動翻訳(後編)
はじめに
前回の記事でご紹介した、ドキュメント翻訳の自動化の実践の続きです。
コンテンツを外国の言語に翻訳するには、バッチ翻訳ジョブを実行することで、容易かつコスト効率よく解決することができます。
しかし、一連のドキュメントを集めたり、そのドキュメントに対して定期的に非同期のバッチ API を呼び出したりすると時間がかかります。
ドキュメントが用意された時点で、すぐに翻訳処理を開始できたほうがいいですよね。AWS Lambda と リアルタイム翻訳を使用する進んだアプローチ
イベント駆動型アーキテクチャを利用することで、簡単に、自然な翻訳を行えるようになります。
特定の S3 バケットにドキュメントがアップロードされたときに、そのバケットから AWS Lambda に通知が送信されるように設定を構成します。
実践の流れ
S3 バケットの通知により、AWS Lambda では、次のようなイベントのシーケンスのためのコードが実行されます。
1. ドキュメントを読み出し S3 バケットにアップロードします。
2. リアルタイム翻訳 API に渡せるように、要素をドキュメントから抽出します。
3. リアルタイム翻訳 API にこの要素を渡します。
さらに、リアルタイム翻訳 API からの出力を使って翻訳済みドキュメントを再構成します。
4. 指定したバケットに翻訳したドキュメントを保存します。ステップ1. CloudFormation を使ったアプリケーションの起動
コンソールを使い、 AWS CloudFormation スタックを起動します。
AWS CloudFormation コンソールで、新しくリソース (標準) を設定し、[Create stack]をクリックします。
[Amazon S3 URL] を選択し、Amazon S3 URL の項目に
https://s3.amazonaws.com/aws-ml-blog/artifacts/serverless-document-translation/translate-lambda-cfn-stack.yml
をコピーします。次に [Next] をクリックします。
ステップ2. S3 バケットを作成して指定する
[Stack name] には、automated-document-translation のように、アカウント内で一意のスタック名を入力します。
[IAMRoleName] には、TranslationLambdaExecRole のように、アカウント内で一意の IAM ロール名を入力します。
[LambdaFunctionName] には、trigger-translation のように、一意の AWS Lambda 関数名を入力します。
[InputBucketName] には、スタックが作成した Amazon S3 バケットのための、一意の名前を入力します。
入力のドキュメントは、翻訳処理前に、このバケットにアップロードされます。
新規の S3 バケットが作成されるため、既存バケットの名前は使わないようにします。
※ 名前が同じものがあると、スタックの構築が失敗します。[OutputBucketName] には、出力バケットのための一意の名前を入力します。
翻訳済みの出力ドキュメントが、このバケットに保存されます。
入力バケットの場合と同様に一意の名前をつけてください。[SourceLanguageCode] では、翻訳前のドキュメントの言語を、コードで入力します。
たとえば、英語を指定する場合は en とし、主として使われている言語を検出させる場合は auto とします。[TargetLanguageCode] には、翻訳後のドキュメントで使う言語を、コードで入力します。
日本語を指定する場合には ja とします。
(使用可能な言語コードの詳細についてはこちら)
[Next] を選択します。
[Configure Stack Options] ページで、スタック用のタグなど、追加のオプションパラメータを選択します。
(特に必要なければいじらなくてOK)
[Next] を選択します。
[I acknowledge that AWS CloudFormation might create IAM resources with custom names.] のチェックボックスをオンにします。
[Create Stack] をクリックします。
スタックの作成が完了するまで、最大 1 分間ほどかかります。ロール(権限)の内訳
Lambda 関数では、このロールが必要な Amazon S3 と Amazon Translate API にアクセスできることを想定しています。
この IAM ロールには、 2 つのポリシーがアタッチされています。1 、入力および出力の S3 バケットに対する、読み出し/書き込みのアクセス権限
(GetObject と PutObject) を与えるカスタムポリシー。
2 、AWS が管理しているポリシー TranslateReadOnly
Amazon Translate への API を呼び出すためのもの。ステップ3. アプリケーションの実行
AWS CloudFormation スタックの作成が終わると、このソリューションを利用開始できます。
デザインを表示させるとこんな構成が出来上がります。視覚的にわかりやすいですね。
入力側の S3 バケットに、翻訳対象のテキストファイルをアップロードします。
これによりワークフローが起動され、処理が完了すると、翻訳済みドキュメントが出力側の S3 バケットに自動的に保存されます。翻訳済みドキュメントは、出力 S3 バケット内の次のようなパスに保存されます。
<TargetLanguageCode>/<original path of the source file>.
たとえば、入力ドキュメントのタイトルが test.txt となっていて、入力 S3 バケット内の in202040413 という名前の S3 フォルダーに保存されているとします。
日本語に翻訳されたドキュメントの保存先は、出力バケット内の 「ja/out20200413/test.txt」 となります。
出力 S3 バケットでドキュメントが見つからない場合は、Amazon CloudWatch Logs で対応する Lambda 関数をチェックし、失敗の原因となっている可能性のあるエラーを探します。
ここでは、UTF-8 形式のテキストドキュメントのみを処理しています。
Lambda 関数での最大実行時間 (timeout) に関する制限があります。結果
今回は一つのファイルに英語の文章をまとめてから、アップロードしました。
今回も違和感のないキレイな日本語になりました!所感
1. 収集したドキュメントに、非同期のバッチ翻訳を行うシンプルな翻訳
2. AWS Lambda と Amazon のリアルタイム翻訳を使い、ドキュメントを入手する度に同期的に翻訳を行う、
より進んだ手法
今回この2つの手法を使ったドキュメント翻訳を行いましたが、1だとバケットを一度作ってしまえば Translate で操作して簡単に行なえますし
2を使えば S3 バケットを前もって作らなくても、自動的な翻訳が一度に一つのコンソール画面で処理できるので、面倒が少なくて済みます。
作業効率もあがりますし、文の長さを気にせず、質の高い翻訳が実現できるので積極的に使っていきたいです!公式サイトリンク
- 投稿日:2020-04-14T15:11:28+09:00
浜松市版新型コロナウイルス対策サイトをAWSで運用する方法
はじめに
浜松市 新型コロナウィルス感染症対策サイトのお手伝いをしています。
浜松市では市内で2020/3/292020/3/28 に初の感染者が確認されてから、市内外のITコミュニティ有志により東京都の新型コロナウィルス感染症対策サイトをForkして4/1から公開を始めました。東京都のサイトはデザインや中に使用されている技術のみならずデプロイまでの運用についてもしっかり出来上がっている素晴らしいものなので地方で立ち上げる場合も非常に短時間で公開できました。
【静岡新聞】 コロナ対策で新サイト 浜松市と市内IT関連有志これから同じように立ち上げようとする方のために主にデプロイに関しての解説をしたいと思います。
派生版を作成するには
派生版を作成する場合のノウハウについては主に下記のサイトにナレッジがまとまっていますのでこちらを参考にたちあげます。
「東京都 新型コロナ対策サイト」地域展開に向けて情報共有のナレッジ特に派生版を作るときにまず、やることリストには技術的な記事以外にも行政とつながるための連絡方法なども書いてあるので一読することをお勧めします。
基本的なデプロイの仕組み
下表の左列に記載されたブランチが更新されると、ブランチとWebサイトの更新が自動的におこなわれます。
この自動化にはGutHub Actionsの機能が使用されています。すでに本家サイトに用意されたワークフローにより、下記の表にあるように
developmentブランチにpushされるとdev-pages
stagingブランチにpushされるとgh-pages
masterブランチにpushされるとproduction
にHTMLがpushされます。
ブランチ HTML類がbuildされ、更新されるブランチ 目的 development
dev-pages
開発用サイト staging
gh-pages
ステージングサイト master
production
本番サイト buildで出来上がったファイルは以下のような構成になりますので本番公開するにはこのフォルダが サイトのトップディレクトリ になるように配置すればWEB公開されます。
https://github.com/tokyo-metropolitan-gov/covid19/tree/productionGitHub Pagesで公開する方法
GitHub Pagesの公開機能を使用してそのままのドメインで公開しようとするとサブディレクトリになってしまいますので中で使用される相対パスがずれてしまい画像やJSが参照できず404になってしまいます。
例 https://tokyo-metropolitan-gov.github.io/covid19/
試してはいませんが、このフォルダがトップディレクトリになるようにカスタムドメインを設定すればGitHub Pagesでも公開できると思います。GitHub Pagesで公開する場合は次の制限があります 「100GB bandwidth/month」「10 builds/hour」
自サイトやさくらインターネットVPSなどで運用する場合
上記で出来上がったproductionブランチのルート以下のフォルダを丸ごとWEBサーバーの公開フォルダにコピーします。
このフォルダがサイトのトップディレクトリ になるようにする必要があります。(試していないですが...多分)さくらインターネットでは新型コロナ情報まとめサイト向けのサーバーを無料提供のサポートを行っています。
Netlifyで公開
東京サイトをはじめとして、多くの派生サイト(2020/4/13現在の浜松版も)ではNetlifyを使用して公開されていることが多いです。
Netlifyの無料枠は「100GB bandwidth/month」「300 build minutes/month」になります。
また、COVID-19のサポートとしてこちらから申請することで2020/3より6か月間上記制限なしで利用することができます。Netlifyを利用したデプロイはすでに以下のような記事が出ていますのでそちらを参考にするとよいと思います。
- 東京都新型コロナウイルス感染症対策サイトをforkしてnetlifyでdev環境を立ち上げる手順
- (東京都 新型コロナウイルス感染症対策サイトで)Netlifyでデプロイプレビューを設定するとレビューが捗るよAmazon S3 で公開
浜松版サイトではAWSからのサポートの提供の申し出があったため、現在のNetlifyでの公開を近日中にAWSを使用した公開に切り替える予定です。
そこで、どのようにしてAWSにデプロイするかを記載します。
S3バケットの作成と、そのバケットの公開設定、バケットにアクセスするためのIAMユーザーの作成は済んでいる前提です。
初めての方は下記のサイトを参考にS3バケットを用意してください。IAMユーザーには作成したバケットに対して読み書きができるような権限を与えておきます。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "s3:GetBucketLocation", "s3:ListBucket", "s3:DeleteObject", "s3:GetObject", "s3:PutObject" ], "Resource": [ "arn:aws:s3:::[バケット名]/*", "arn:aws:s3:::[バケット名]" ] } ] }作成した
バケット名
とリージョン
および、作成したIAMユーザーのAccess key ID
とSecret_Access_Key
を後述するスクリプトで使用するため控えておいてくださいGitHub Actionsの設定
GitHub ActionsではGitHubレポジトリに対しての何らかのイベントをトリガーとして何らかのアクションを実行します。
GitHub Actionsのワークフローは .github/workflowsに入っており、主にCOVID-19サイトのデプロイに関するワークフローは以下のものが用意されています。
- developブランチにプッシュしたときにdev-pagesへデプロイするワークフローは
develop.yml
- stagingブランチにプッシュしたときにgh-pagesへデプロイするワークフローは
staging.yml
- masterブランチにプッシュしたときにproductionへデプロイするワークフローは
deploy.yml
実行時には先ほど作成したIAMユーザーのACCESS_KEY_ID,SECRET_ACCESS_KEY が必要になります。
Forkしたブランチの[Settings]-[Secrets]にスクリプトに使用しているキーで保存しておきます
今回は、staging.ymlを修正してS3にデプロイする処理を加えます。(他のものも適宜ブランチ名、バケット名など変更すればOK)
.github/workflows/staging.ymlname: staging deploy on: push: branches: - staging jobs: deploy: runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v2 - name: Setup Node uses: actions/setup-node@v1 with: node-version: '10.x' - name: Cache dependencies uses: actions/cache@v1 with: path: ~/.cache/yarn key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} restore-keys: | ${{ runner.os }}-yarn- - run: yarn install --frozen-lockfile - run: yarn run test - run: yarn run generate:dev --fail-on-page-error - run: "echo \"User-agent: *\nDisallow: /\" > ./dist/robots.txt" - name: deploy uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./dist # S3デプロイのために今回追加する箇所 - name: deploy to s3 uses: jakejarvis/s3-sync-action@master with: args: --acl public-read --follow-symlinks --delete env: AWS_S3_BUCKET: '用意したバケット名' AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_REGION: 'バケットがあるリージョン' # 東日本ならば ap-northeast-1 SOURCE_DIR: './dist'完成イメージ
上記のワークフローファイルをコミットしてstagingブランチにプッシュすると、コミットしたワークフローが走り出し gh-pages と S3にデプロイされます。
最後に
浜松市版新型コロナウイルス対策サイトの運営は東京サイトに比べて人数も少なく、特定の人にタスクが集中してしまう状況にあります。是非興味がありましたら気軽に下記のリンクから一緒に参加してみませんか?
浜松市 新型コロナウイルス対策サイト↓
https://stopcovid19-hamamatsu.netlify.com/
GitHubリポジトリ
https://github.com/code-for-hamamatsu/covid19
Slack
https://join.slack.com/t/jaws-ug-hamamatsu/shared_invite/zt-dc5cgs87-cNw8QOxXeqhJnB8YB8A6Uwリンク
浜松市 新型コロナウイルス対策サイトのコントリビューター @w2or3w さんの記事
静岡県オープンデータカタログ(csv)からCOVID-19対策サイトのデータ(json)に変換して取得するAPI
https://qiita.com/w2or3w/items/55ff3159aea0c7a9e096
- 投稿日:2020-04-14T14:14:26+09:00
AWS EC2でサーバを構築 7 - セキュリティ対策
記事一覧
- AWS EC2でサーバを構築 1 - Amazon Linux 2 準備編
- AWS EC2でサーバを構築 2 - 各種インストール編
- AWS EC2でサーバを構築 3 - Apache + Let's Ecnrypt + PHP-FPM編 (Nginxに変更)
- AWS EC2でサーバを構築 4 - Nginx + Let's Ecnrypt + PHP-FPM編 (脆弱性診断「A+」を狙う)
- AWS EC2でサーバを構築 5 - MySQL + phpMyAdmin
- AWS EC2でサーバを構築 6 - PostfixとDovecot (SSL対応とSPAM対策)
- AWS EC2でサーバを構築 7 - セキュリティ対策
概要
EC2上に構築したサーバを運用するうえで必要となるセキュリティ対策です。
前回までの記事でサーバ構築が完了していることが前提です。
セキュリティグループ
AWSのセキュリティグループがファイアウォールの役割を果たします。
外部公開が必要となるポートだけをインバウンドルールに追加します(不要なポートを開けないように)。
インバウンドルール
タイプ プロトコル ポート範囲 ソース SSH TCP 22 0.0.0.0/0 HTTP TCP 80 0.0.0.0/0 HTTPS TCP 443 0.0.0.0/0 SMTP TCP 25 0.0.0.0/0 SMTPS TCP 465 0.0.0.0/0 IMAPS TCP 993 0.0.0.0/0 POP3S TCP 995 0.0.0.0/0 SMTPSが有効でも、25/tcpを許可しないとメール送受信ができないので注意してください。
Fail2ban
/var/log
にある様々なログを監視し、アクセス失敗(多くは不正アクセス試行)を独自に管理しBan/Unbanします。以下の設定内容はこのような内容になります。
- 10分間で5回アクセス失敗したIPアドレスを10分間Banする
- 24時間に5回BanされたIPアドレスを7日間Banする(再犯対策)
- サーバ自身と管理者PC(例では123.456.78.90)は監視の対象外とする
/etc/fail2ban/jail.local
[DEFAULT] backend = systemd ignoreip = 127.0.0.0/8 10.0.0.0/16 123.456.78.90 destemail = root@example1.com sender = fail2ban@example1.com banaction = firewallcmd-ipset bantime = 600 findtime = 600 maxretry = 5 [sshd] enabled = true [postfix-sasl] enabled = true [dovecot] enabled = true [recidive] enabled = true bantime = 604800 findtime = 86400 maxretry = 5Logwatch対応
LogwatchがFail2banのログを拾ってくれない問題に対処します。
/usr/share/logwatch/scripts/services/fail2ban
} elsif ( my ($Service,$Action,$Host) = ($ThisLine =~ m/WARNING:?\s\[?(.*?)[]:]?\s(Ban|Unban)[^\.]* (\S+)/)) {↓ このように変更します。
} elsif ( my ($Service,$Action,$Host) = ($ThisLine =~ m/(?:WARNING|NOTICE):?\s+\[?(.*?)[]:]?\s(Ban|Unban)[^\.]* (\S+)/)) {"具体的には
WARNING:?\s
を(?:WARNING|NOTICE):?\s+
に変更しています。Fail2ban起動
systemctl start fail2banステータス確認
fail2ban-client status sshd以下のように表示されます。
Status for the jail: sshd |- Filter | |- Currently failed: 1 | |- Total failed: 2118 | `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd `- Actions |- Currently banned: 4 |- Total banned: 59 `- Banned IP list: 27.78.14.83 70.37.84.164 193.142.146.21 116.105.216.179Logwatchの例
Logwatchからのメールでは以下のように記載されます。
--------------------- fail2ban-messages Begin ------------------------ Banned services with Fail2Ban: Bans:Unbans sshd: [ 12:6 ] ---------------------- fail2ban-messages End -------------------------サーバでの対応
以下はここまでの記事で設定済みです。
- 定期的にパッケージのアップデートを行う(
yum update
)- 必要のないポートを外部公開しない(セキュリティグループ)
- SSHへのパスワードアクセスを禁止(公開鍵認証のみ)
- FTPサーバを起動しない(Git over SSHやSFTPで代用可能)※
- MySQL (3306/tcp) を外部に公開しない
- 使えるところはすべてSSL通信を行う(SSH, Nginx, Postfix, Dovecot)
- SSL/TLSの古いプロトコルや暗号スイートを使用しない(Nginx)
- 非公開領域にはBASIC認証やアプリケーションでの認証を設定(Nginx)
- 古いバージョンのPHPを使用しない(新規構築なら最低でもPHP 7.3系)
- SPAM対策を行う(Postfix / SMTP認証、RBLデータベース参照)
- 不正アクセスを対策する(Fail2ban)
- ログに目を通す(Logwatch)
※あるクライアントが自社サーバの脆弱性診断を業者に依頼したところ、FTP関連の脆弱性が多くを占めていました。
さらなる対策
- ファイルの改竄検知を行う(AuditやTripwire等)
- ウィルス検知を行う(ClamAV等)
- SPAM検知を強化する(SpamAssassin等)
- 独自に設定したアラートをSlack等へ飛ばす
- Webアプリケーションの脆弱性に気を配る(WordPress等)
他にもできることは多いですが、割愛(もしくは今後記事化)します。
- 投稿日:2020-04-14T12:58:51+09:00
AWS EC2でサーバを構築 6 - PostfixとDovecot (SSL対応)
概要
PostfixとDovecotでメールサーバを構築します。SSL化とSMTP認証を取り入れます。
前回までの作業が完了している前提です。
Postfix
メインドメインがexample1.comで、こちらでSSL証明書を取得します。
メールクライアントのサーバ設定では、~@example2.comであっても受信/送信サーバ共にmail.example1.comを指定します。
SMTP認証にはDovecotを使います。
/etc/postfix/main.cf
myhostname = mail.example1.com mydomain = example1.com myorigin = $mydomain inet_interfaces = all inet_protocols = ipv4 home_mailbox = Maildir/ smtpd_banner = $myhostname ESMTP unknown # virtual_alias # virtual_alias_maps = hash:/etc/postfix/virtual virtual_alias_domains = example2.com # spam block - 2020.04.07 # disable_vrfy_command = yes smtpd_delay_reject = yes smtpd_helo_required = yes smtpd_helo_restrictions = permit_mynetworks, reject_non_fqdn_hostname, reject_invalid_hostname, permit smtpd_error_sleep_time = 1s smtpd_soft_error_limit = 5 smtpd_hard_error_limit = 10 smtpd_client_message_rate_limit = 6 smtpd_client_recipient_rate_limit = 6 # smtp-auth # smtpd_sasl_auth_enable = yes smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth smtpd_recipient_restrictions = permit_sasl_authenticated reject_invalid_hostname, reject_non_fqdn_hostname, reject_non_fqdn_sender, reject_non_fqdn_recipient, reject_unknown_sender_domain, reject_unknown_recipient_domain, permit_mynetworks, reject_rbl_client all.rbl.jp, reject_rbl_client bl.spamcop.net, reject_rbl_client zen.spamhaus.org, permit broken_sasl_auth_clients = yes # tls/ssl # smtpd_use_tls = yes smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example1.com/fullchain.pem smtpd_tls_key_file = /etc/letsencrypt/live/mail.example1.com/privkey.pem smtp_tls_security_level = may smtpd_tls_loglevel = 1 smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache smtpd_tls_session_cache_timeout = 3600sTLS有効化
SMTPSを使うための設定を行います。必要な部分をコメントインします。
/etc/postfix/master.cf
smtps inet n - n - - smtpd # -o syslog_name=postfix/smtps -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes # -o smtpd_reject_unlisted_recipient=noSSL証明書取得
メールサーバmail.example1.com用にLet's Ecnryptの証明書を取得します。Nginxと同様の手順です。
80/tcpで待ち受ける必要があるため、Nginxの設定で443/tcpにリダイレクトする設定があればコメントアウトしておきます。
certbot certonly --webroot -w /var/www/html/www.example1.com/public_html/ -d mail.example1.com -m root@example1.comエイリアス設定
root宛のメールを別ユーザーへ転送します。
/etc/alises
root: example1上記設定を反映させるためには以下作業が必要です。
newaliasesバーチャルドメイン設定
メインドメインであるexample1.comはバーチャルドメインにできません。
/etc/postfix/virtual (作成)
example2.com anything info@example2.com example2上記ファイルを更新したら
postmap
が必要です。postmap virtualDovecot
使用プロトコルとポートを指定します。実際使うのはIMAPSとPOP3Sですが、ここでは
imap pop3
と書きます。/etc/dovecot/dovecot.conf
#protocols = imap pop3 lmtp protocols = imap pop3 #listen = *, :: listen = *認証関連
標準的なメーラーの初期設定、自動認識に対応させます。
/etc/dovecot/conf.d/10-auth.conf
#disable_plaintext_auth = yes disable_plaintext_auth = no # auth_mechanisms = plain auth_mechanisms = plain loginメールボックス
mbox形式からMaildir形式に変更します。
/etc/dovecot/conf.d/10-mail.conf
#mail_location = mail_location = maildir:~/Maildirプロトコルとポート
IMAPとPOP3は使わず、SSL経由のIMAPSとPOP3Sを使うよう設定します。
PostfixもSMTPSを使うので、これでメール関連はすべてSSL通信に対応できます。
/etc/dovecot/conf.d/10-master.conf
service imap-login { inet_listener imap { #port = 143 port = 0 } inet_listener imaps { #port = 993 port = 993 #ssl = yes ssl = yes } service pop3-login { inet_listener pop3 { #port = 110 port = 0 } inet_listener pop3s { #port = 995 port = 995 #ssl = yes ssl = yes } # Postfix smtp-auth #unix_listener /var/spool/postfix/private/auth { # mode = 0666 #} unix_listener /var/spool/postfix/private/auth { mode = 0666 user = postfix group = postfix }SSL設定
Let's Ecnryptで取得したメールサーバ用の証明書を指定します。
/etc/dovecot/conf.d/10-ssl.conf
#ssl_cert = </etc/pki/dovecot/certs/dovecot.pem #ssl_key = </etc/pki/dovecot/private/dovecot.pem ssl_cert = </etc/letsencrypt/live/mail.example1.com/fullchain.pem ssl_key = </etc/letsencrypt/live/mail.example1.com/privkey.pemPostfixとDovecotを起動します。
systemctl start postfix dovecot
- 投稿日:2020-04-14T12:58:51+09:00
AWS EC2でサーバを構築 6 - PostfixとDovecot (SSL対応とSPAM対策)
記事一覧
- AWS EC2でサーバを構築 1 - Amazon Linux 2 準備編
- AWS EC2でサーバを構築 2 - 各種インストール編
- AWS EC2でサーバを構築 3 - Apache + Let's Ecnrypt + PHP-FPM編 (Nginxに変更)
- AWS EC2でサーバを構築 4 - Nginx + Let's Ecnrypt + PHP-FPM編 (脆弱性診断「A+」を狙う)
- AWS EC2でサーバを構築 5 - MySQL + phpMyAdmin
- AWS EC2でサーバを構築 6 - PostfixとDovecot (SSL対応とSPAM対策)
- AWS EC2でサーバを構築 7 - セキュリティ対策
概要
PostfixとDovecotでメールサーバを構築します。SSL化とSMTP認証、SPAM対策を取り入れます。
Postfix
メインドメインがexample1.comで、こちらでSSL証明書を取得します。
メールクライアントの送受信サーバ設定では、example2.comのメールアカウントであってもmail.example1.comを指定します。
SMTP認証にはDovecotを使います。SPAM対策のためRBLを参照するよう設定します。
/etc/postfix/main.cf
myhostname = mail.example1.com mydomain = example1.com myorigin = $mydomain inet_interfaces = all inet_protocols = ipv4 home_mailbox = Maildir/ smtpd_banner = $myhostname ESMTP unknown # virtual_alias # virtual_alias_maps = hash:/etc/postfix/virtual virtual_alias_domains = example2.com # spam block - 2020.04.07 # disable_vrfy_command = yes smtpd_delay_reject = yes smtpd_helo_required = yes smtpd_helo_restrictions = permit_mynetworks, reject_non_fqdn_hostname, reject_invalid_hostname, permit smtpd_error_sleep_time = 1s smtpd_soft_error_limit = 5 smtpd_hard_error_limit = 10 smtpd_client_message_rate_limit = 6 smtpd_client_recipient_rate_limit = 6 # smtp-auth # smtpd_sasl_auth_enable = yes smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth smtpd_recipient_restrictions = permit_sasl_authenticated reject_invalid_hostname, reject_non_fqdn_hostname, reject_non_fqdn_sender, reject_non_fqdn_recipient, reject_unknown_sender_domain, reject_unknown_recipient_domain, permit_mynetworks, reject_rbl_client all.rbl.jp, reject_rbl_client bl.spamcop.net, reject_rbl_client zen.spamhaus.org, permit broken_sasl_auth_clients = yes # tls/ssl # smtpd_use_tls = yes smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example1.com/fullchain.pem smtpd_tls_key_file = /etc/letsencrypt/live/mail.example1.com/privkey.pem smtp_tls_security_level = may smtpd_tls_loglevel = 1 smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache smtpd_tls_session_cache_timeout = 3600sTLS有効化
SMTPSを使うための設定を行います。必要な部分をコメントインします。
/etc/postfix/master.cf
smtps inet n - n - - smtpd # -o syslog_name=postfix/smtps -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes # -o smtpd_reject_unlisted_recipient=noSSL証明書取得
メールサーバmail.example1.com用にLet's Ecnryptの証明書を取得します。Nginxと同様の手順です。
80/tcpで待ち受ける必要があるため、Nginxの設定で443/tcpにリダイレクトする設定があればコメントアウトしておきます。
certbot certonly --webroot -w /var/www/html/www.example1.com/public_html/ -d mail.example1.com -m root@example1.comエイリアス設定
root宛のメールを別ユーザーへ転送します。
/etc/alises
root: example1上記設定を反映させるためには以下作業が必要です。
newaliasesバーチャルドメイン設定
メインドメインであるexample1.comはバーチャルドメインにできません。
/etc/postfix/virtual (作成)
example2.com anything info@example2.com example2上記ファイルを更新したら
postmap
が必要です。postmap virtualDovecot
使用プロトコルとポートを指定します。実際使うのはIMAPSとPOP3Sですが、ここでは
imap pop3
と書きます。/etc/dovecot/dovecot.conf
#protocols = imap pop3 lmtp protocols = imap pop3 #listen = *, :: listen = *認証関連
標準的なメーラーの初期設定、自動認識に対応させます。
/etc/dovecot/conf.d/10-auth.conf
#disable_plaintext_auth = yes disable_plaintext_auth = no # auth_mechanisms = plain auth_mechanisms = plain loginメールボックス
mbox形式からMaildir形式に変更します。
/etc/dovecot/conf.d/10-mail.conf
#mail_location = mail_location = maildir:~/Maildirプロトコルとポート
IMAPとPOP3は使わず、SSL経由のIMAPSとPOP3Sを使うよう設定します。
PostfixもSMTPSを使うので、これでメール関連はすべてSSL通信に対応できます。
/etc/dovecot/conf.d/10-master.conf
service imap-login { inet_listener imap { #port = 143 port = 0 } inet_listener imaps { #port = 993 port = 993 #ssl = yes ssl = yes } service pop3-login { inet_listener pop3 { #port = 110 port = 0 } inet_listener pop3s { #port = 995 port = 995 #ssl = yes ssl = yes } # Postfix smtp-auth #unix_listener /var/spool/postfix/private/auth { # mode = 0666 #} unix_listener /var/spool/postfix/private/auth { mode = 0666 user = postfix group = postfix }SSL設定
Let's Ecnryptで取得したメールサーバ用の証明書を指定します。
/etc/dovecot/conf.d/10-ssl.conf
#ssl_cert = </etc/pki/dovecot/certs/dovecot.pem #ssl_key = </etc/pki/dovecot/private/dovecot.pem ssl_cert = </etc/letsencrypt/live/mail.example1.com/fullchain.pem ssl_key = </etc/letsencrypt/live/mail.example1.com/privkey.pemPostfixとDovecotを起動します。
systemctl start postfix dovecot
- 投稿日:2020-04-14T12:45:41+09:00
AWS EC2でサーバを構築 5 - MySQL + phpMyAdmin
記事一覧
- AWS EC2でサーバを構築 1 - Amazon Linux 2 準備編
- AWS EC2でサーバを構築 2 - 各種インストール編
- AWS EC2でサーバを構築 3 - Apache + Let's Ecnrypt + PHP-FPM編 (Nginxに変更)
- AWS EC2でサーバを構築 4 - Nginx + Let's Ecnrypt + PHP-FPM編 (脆弱性診断「A+」を狙う)
- AWS EC2でサーバを構築 5 - MySQL + phpMyAdmin
- AWS EC2でサーバを構築 6 - PostfixとDovecot (SSL対応とSPAM対策)
- AWS EC2でサーバを構築 7 - セキュリティ対策
概要
Amazon Linux 2を含むRHEL (RedHat Enterprise Linux) 系のOSでは、MySQLから派生したMariaDBがデフォルトで採用されています。これについての経緯は省きますが、Oracleによる買収後も従来通りに利用可能であるため、互換性重視でMySQLを採用します。
MySQLはサーバリソースを食うため、アクセス数や負荷が増えたらRDSへのリプレースも検討した方が良いでしょう。
MySQL
デフォルトのキャラセットを変更します。
今回、特にパフォーマンスチューニングは行いません。
/etc/my.cnf
character-set-server = utf8以下は最初に行う儀式的なコマンドです。root@localhostのパスワードを変更します。
mysql_secure_installationMySQLを停止します。
systemctl stop mysqldデフォルトでは難解なパスワードしか認められずエラーになるのでこれを回避する設定です。
mysql -u root -p > set global validate_password_policy=LOW; > quit改めてMySQLを起動します。
systemctl start mysqldphpMyAdmin
設定ファイルのサンプルをコピーして設定ファイルを作成します。
cd /var/www/html/www.example1.com/public_html/phpmyadmin cp config.sample.inc.php config.inc.php/var/www/html/dev.netartz.com/public_html/config.inc.php
phpMyAdminはすぐにセッションが切れてしまい再ログインが手間なので、セッションが24時間持続するようにします。
$cfg['blowfish_secret'] = '{記号を含む長いランダムな文字列}'; /* YOU MUST FILL IN THIS FOR COOKIE AUTH! */ $cfg['LoginCookieValidity'] = 86400;phpMyAdminにログインして
phpmyadmin
データベースを作成し、SQL文をインポートします。mysql -uroot -p phpmyadmin < ./sql/create_tables.sql mkdir tmp chmod 777 tmp
- 投稿日:2020-04-14T12:21:35+09:00
AWS EC2でサーバを構築 4 - Nginx + Let's Ecnrypt + PHP-FPM編 (脆弱性診断「A+」を狙う)
記事一覧
- AWS EC2でサーバを構築 1 - Amazon Linux 2 準備編
- AWS EC2でサーバを構築 2 - 各種インストール編
- AWS EC2でサーバを構築 3 - Apache + Let's Ecnrypt + PHP-FPM編 (Nginxに変更)
- AWS EC2でサーバを構築 4 - Nginx + Let's Ecnrypt + PHP-FPM編 (脆弱性診断「A+」を狙う)
- AWS EC2でサーバを構築 5 - MySQL + phpMyAdmin
- AWS EC2でサーバを構築 6 - PostfixとDovecot (SSL対応とSPAM対策)
- AWS EC2でサーバを構築 7 - セキュリティ対策
概要
Nginx、SSL (Let's Ecnrypt)、PHP-FPMの設定を行います。また脆弱性診断で最高の「A+」を狙います。
Apacheを設定済みの場合は削除するか、
systemctl disable httpd
しておいてください。削除を推奨します。脆弱性診断結果
結論から書いてしまいますが、以下の設定でSSL Labsの脆弱性診断を行ったところ最高の「A+」となりました。
当初は「A」でしたが、設定を見直して「A+」を達成できました。以下の通りの設定で「執筆時点では」「A+」になるはずです。
Nginx
エラー画面でバージョンを吐かないようにし、SSLに関するデフォルト設定を書いておきます。
ここが脆弱性診断「A+」のキモとなります。
注意:以下は
server
ではなくhttp
ディレクティブに追加してください。/etc/nginx/nginx.conf
server_tokens off; ssl_protocols TLSv1.2; ssl_stapling on; ssl_stapling_verify on; ssl_session_cache shared:SSL:50m; ssl_session_timeout 1d; ssl_ciphers HIGH:MEDIUM:!aNULL:!MD5:!SEED:!IDEA:!3DES:!RC4:!DH; ssl_prefer_server_ciphers on; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";Amazon Linux 2のOpenSSLが1.0.2kなので、OpenSSL 1.1.1以降が必要となるTLSv1.3は設定できません。
バーチャルホスト
バーチャルホスト用に公開ディレクトリを作成しておきます。
Apacheとの互換を維持するため、
var/www
で始まりpublic_html
で終わるようにしています。mkdir -p /var/www/html/www.example1.com/public_html mkdir -p /var/www/html/www.example2.com/public_html chown -R nginx. /var/www/html普段は常時SSL設定で良いのですが、Let's Ecnryptの
certbot
が80/tcpへの接続を求めるためreturn
の行はコメントアウトで切り替えて使います。301リダイレクトしている80/tcpのディレクティブにも
root
行があるのはそのためです。また設定ファイル内でドメイン正規化 (wwwありに統一) を行います。Apacheの
.htaccess
が使えないためです。/etc/nginx/conf.d/www.example1.com.conf
server { listen 80; listen 443 ssl http2; server_name example1.com; return 301 https://www.$host$request_uri; ssl_certificate "/etc/letsencrypt/live/example1.com/fullchain.pem"; ssl_certificate_key "/etc/letsencrypt/live/example1.com/privkey.pem"; include /etc/nginx/default.d/*.conf; } server { listen 80; server_name www.example1.com; root /var/www/html/www.example1.com/public_html; return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name www.example1.com; root /var/www/html/www.example1.com/public_html; ssl_certificate "/etc/letsencrypt/live/www.example1.com/fullchain.pem"; ssl_certificate_key "/etc/letsencrypt/live/www.example1.com/privkey.pem"; include /etc/nginx/default.d/*.conf; location / { } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } }Aapcheの例と同じく、www.example2.comはBASIC認証を設定します。
生成サービスを利用して暗号化パスワードを生成しておきます。
/var/www/html/www.example2.com/.htpasswd
{ユーザー名}:{暗号化されたパスワード}Apacheと異なり.htaccessが使えないため、設定ファイル内にBASIC認証の設定を記述します。
/etc/nginx/conf.d/www.example2.com.conf
server { listen 80; server_name www.example2.com; root /var/www/html/www.example2.com/public_html; return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name www.example2.com; root /var/www/html/www.example2.com/public_html; ssl_certificate "/etc/letsencrypt/live/www.example2.com/fullchain.pem"; ssl_certificate_key "/etc/letsencrypt/live/www.example2.com/privkey.pem"; include /etc/nginx/default.d/*.conf; location / { auth_basic "Enter your ID and Password"; auth_basic_user_file /var/www/html/www.example2.com/.htpasswd; } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } }SSL証明書取得
Let's Ecnryptの証明書を取得します。
certbot certonly --webroot -w /var/www/html/www.example1.com/public_html/ -d example1.com -m root@example1.com certbot certonly --webroot -w /var/www/html/www.example1.com/public_html/ -d www.example1.com -m root@example1.com certbot certonly --webroot -w /var/www/html/www.example2.com/public_html/ -d www.example2.com -m root@example1.com証明書の自動更新
月曜と木曜の4時0分に自動更新されるようにします。
Let's Ecnrypt証明書の期限は3ヶ月です。更新は週に5回までの制限があります。
crontab -e
0 4 * * 1,4 certbot renew --post-hook "systemctl restart nginx php-fpm postfix dovecot"CAAレコード追加
脆弱性診断への対策のため、DNSサーバ (ネームサーバ) でCAAレコードを追加します。
できない場合やわからない場合は読み飛ばしてください。ただし診断結果に「若干」影響する可能性があります。
example1.com. 3600 IN CAA 0 issue "letsencrypt.org"
example2com. 3600 IN CAA 0 issue "letsencrypt.org"
PHP-FPM
まずはPHPそのものの設定を行います。環境によって調整してください。
/etc/php.ini
;expose_php = On expose_php = Off ; max_execution_time = 30 max_execution_time = 120 ; memory_limit = 128M memory_limit = 256M ; post_max_size = 8M post_max_size = 128M ; upload_max_filesize = 2M upload_max_filesize = 128M ;date.timezone = date.timezone = Asia/Tokyo ; session.gc_maxlifetime = 1440 session.gc_maxlifetime = 86400チューニング
実行ユーザー/グループの設定とパフォーマンスチューニングの設定を行います。環境によって調整してください。
/etc/php-fpm.d/www.conf
; user = apache user = nginx ; group = apache group = nginx ;listen.owner = nobody ;listen.group = nobody ;listen.mode = 0660 listen.owner = nginx listen.group = nginx listen.mode = 0660 ; pm.max_children = 50 pm.max_children = 30 ; pm.start_servers = 5 pm.start_servers = 10 ; pm.min_spare_servers = 5 pm.min_spare_servers = 10 ; pm.max_spare_servers = 35 pm.max_spare_servers = 25 ;pm.max_requests = 500 pm.max_requests = 30NginxとPHP-FPMを再起動します。これは設定を変更するたびに行います。
systemctl restart nginx php-fpmComposer
Laravel等で使用するcomposerをインストールしておきます。
curl -sS https://getcomposer.org/installer | php mv composer.phar /usr/local/bin/composerトラブルシューティング
/var/lib/php
内のセッションやキャッシュ用ディレクトリの所有グループがapacheになっている場合の対処法です。chgrp nginx /var/lib/php/opcache chgrp nginx /var/lib/php/session chgrp nginx /var/lib/php/wsdlcacheセッションについては中のファイルが
apache:apache
な状態になっている場合があるので修正。chown nginx. /var/lib/php/sesion/*
- 投稿日:2020-04-14T11:42:46+09:00
AWS EC2でサーバを構築 3 - Apache + Let's Ecnrypt + PHP-FPM編 (Nginxに変更)
記事一覧
- AWS EC2でサーバを構築 1 - Amazon Linux 2 準備編
- AWS EC2でサーバを構築 2 - 各種インストール編
- AWS EC2でサーバを構築 3 - Apache + Let's Ecnrypt + PHP-FPM編 (Nginxに変更)
- AWS EC2でサーバを構築 4 - Nginx + Let's Ecnrypt + PHP-FPM編 (脆弱性診断「A+」を狙う)
- AWS EC2でサーバを構築 5 - MySQL + phpMyAdmin
- AWS EC2でサーバを構築 6 - PostfixとDovecot (SSL対応とSPAM対策)
- AWS EC2でサーバを構築 7 - セキュリティ対策
概要
ウェブサーバをApacheからNginxに変更したので本作業は不要です。
Apacheで構築したい場合を除き、本記事は読み飛ばしてください。Apache (Event MPM) とSSL (Let's Ecnrypt)、PHP-FPMを設定します。
Apahce
管理者メールアドレス等、お決まりの項目は除いて説明します。以下は気をつける部分です。
/etc/httpd/conf/httpd.conf
<Directory "/var/www/html"> ... #Options Indexes FollowSymLinks Options FollowSymLinks ExecCGI MultiViews #AllowOverride None AllowOverride All#AddHandler cgi-script .cgi AddHandler cgi-script .cgiバーチャルホスト
バーチャルホスト用に公開ディレクトリを作成しておきます。
mkdir -p /var/www/html/www.example1.com/public_html mkdir -p /var/www/html/www.example2.com/public_html chown -R apache. /var/www/htmlLet's Ecnryptが80/tcpを使用するため、それを待ち受ける仮設定をしておきます。
/etc/httpd/conf.d/vhosts.conf
<VirtualHost *:80> ServerName www.example1.com ServerAlias example1.com DocumentRoot /var/www/www.example1.com/public_html CustomLog logs/www.example1.com.access_log combined ErrorLog logs/www.example1.com.error_log </VirtualHost> <VirtualHost *:80> ServerName www.example2.com DocumentRoot /var/www/www.example2.com/public_html CustomLog logs/www.example2.com.access_log combined ErrorLog logs/www.example2.com.error_log </VirtualHost>Apacheを起動しておきます。
systemctl start httpdSSL証明書取得
Let's Ecnryptの証明書を取得します。
certbot certonly --webroot -w /var/www/html/www.example1.com/public_html/ -d example1.com -m root@example1.com certbot certonly --webroot -w /var/www/html/www.example1.com/public_html/ -d www.example1.com -m root@example1.com certbot certonly --webroot -w /var/www/html/www.example2.com/public_html/ -d www.example2.com -m root@example2.com証明書の自動更新
月曜と木曜の4時0分に自動更新されるようにします。
Let's Ecnrypt証明書の期限は3ヶ月です。更新は週に5回までの制限があります。
crontab -e
0 4 * * 1,4 certbot renew --post-hook "systemctl restart httpd php-fpm postfix dovecot"バーチャルホスト (SSL対応)
証明書取得後のバーチャルホスト設定を行います。常時SSL化も行います。
ドメイン正規化 (wwwあり/なし) は
.htaccess
で行う想定です。/etc/httpd/conf.d/vhosts.conf
<VirtualHost *:80> ServerName www.example1.com ServerAlias example1.com Redirect permanent / https://www.example1.com/ </VirtualHost> <VirtualHost *:80> ServerName www.example2.com DocumentRoot /var/www/html/www.example2.com/public_html # Redirect permanent / https://www.example2.com/ </VirtualHost> <VirtualHost *:443> ServerName www.example1.com ServerAlias example1.com DocumentRoot /var/www/www.example1.com/public_html CustomLog logs/www.example1.com.access_log combined ErrorLog logs/www.example1.com.error_log SSLEngine on SSLCertificateFile /etc/letsencrypt/live/www.example1.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/www.example1.com/privkey.pem SSLCertificateChainFile /etc/letsencrypt/live/www.example1.com/chain.pem </VirtualHost> <VirtualHost *:443> ServerName www.example2.com DocumentRoot /var/www/html/www.example2.com/public_html CustomLog logs/www.example2.com.access_log combined ErrorLog logs/www.example2.com.error_log SSLEngine on SSLCertificateFile /etc/letsencrypt/live/www.example2.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/www.example2.com/privkey.pem SSLCertificateChainFile /etc/letsencrypt/live/www.example2.com/chain.pem </VirtualHost>CAAレコード追加
脆弱性診断への対策のため、DNSサーバ (ネームサーバ) でCAAレコードを追加します。
できない場合やわからない場合は読み飛ばしてください。ただし診断結果に「若干」影響する可能性があります。
example1.com. 3600 IN CAA 0 issue "letsencrypt.org"
example2com. 3600 IN CAA 0 issue "letsencrypt.org"
MPM変更
ApacheのMPMを古いPreforkからEventに切り替えます。
# LoadModule mpm_prefork_module modules/mod_mpm_prefork.so LoadModule mpm_event_module modules/mod_mpm_event.soチューニング
パフォーマンスチューニング設定です。環境に合わせて調整してください。
/etc/httpd/conf.d/performance.conf
# HostnameLookups off <IfModule mpm_event_module> StartServers 2 MinSpareThreads 2 MaxSpareThreads 12 ThreadsPerChild 2 MaxRequestWorkers 36 MaxRequestsPerChild 0 </IfModule>モジュール版PHP廃止
PHP-FPM (FastCGI) を動かすため、モジュール版を使用しないよう設定します。
/etc/httpd/conf.d/php.conf
# <FilesMatch \.(php|phar)$> # SetHandler application/x-httpd-php # </FilesMatch>BASIC認証
www.example2.com全体をBASIC認証で保護する想定です。
生成サービスを利用してパスワードファイルを作成しておきます。
/var/www/html/www.example2.com/.htpasswd
{ユーザー名}:{暗号化されたパスワード}
.htaccessでBASIC認証を有効にします。
/var/www/html/www.example2.com/public_html/.htaccess
AuthType Basic AuthName "Enter your ID and password" AuthUserFile /var/www/html/www.example2.com/.htpasswd require valid-user
chown -R dev. /var/www/html/www.example2.comPHP-FPM
まずはPHPそのものの設定を行います。環境によって調整してください。
/etc/php.ini
;expose_php = On expose_php = Off ; max_execution_time = 30 max_execution_time = 120 ; memory_limit = 128M memory_limit = 256M ; post_max_size = 8M post_max_size = 128M ; upload_max_filesize = 2M upload_max_filesize = 128M ;date.timezone = date.timezone = Asia/Tokyo ; session.gc_maxlifetime = 1440 session.gc_maxlifetime = 86400チューニング
パフォーマンスチューニングの設定を行います。環境によって調整してください。
/etc/php-fpm.d/www.conf
; pm.max_children = 50 pm.max_children = 30 ; pm.start_servers = 5 pm.start_servers = 10 ; pm.min_spare_servers = 5 pm.min_spare_servers = 10 ; pm.max_spare_servers = 35 pm.max_spare_servers = 25 ;pm.max_requests = 500 pm.max_requests = 30ApacheとPHP-FPMを再起動します。
systemctl restart httpd php-fpmComposer
Laravel等で使用するcomposerをインストールしておきます。
curl -sS https://getcomposer.org/installer | php mv composer.phar /usr/local/bin/composer
- 投稿日:2020-04-14T11:15:09+09:00
AWS EC2でサーバを構築 2 - 各種インストール編
記事一覧
- AWS EC2でサーバを構築 1 - Amazon Linux 2 準備編
- AWS EC2でサーバを構築 2 - 各種インストール編
- AWS EC2でサーバを構築 3 - Apache + Let's Ecnrypt + PHP-FPM編 (Nginxに変更)
- AWS EC2でサーバを構築 4 - Nginx + Let's Ecnrypt + PHP-FPM編 (脆弱性診断「A+」を狙う)
- AWS EC2でサーバを構築 5 - MySQL + phpMyAdmin
- AWS EC2でサーバを構築 6 - PostfixとDovecot (SSL対応とSPAM対策)
- AWS EC2でサーバを構築 7 - セキュリティ対策
概要
サーバアプリケーションを中心に各種インストールを行います。
設定は次回以降の記事で行います。
ApahceとSSLウェブサーバをApacheからNginxに変更したためインストール不要です。飛ばしてください。
SSL証明書取得用にLet's Ecnryptの
certbot
もインストールします。yum install httpd mod_ssl certbot systemctl enable httpdNginxとSSL
EPELにもNginxはありますが、AWSなのでamazon-linux-extraからインストールします。
SSL証明書取得用にLet's Ecnryptの
certbot
もインストールします。amazon-linux-extras install nginx1 yum install certbot systemctl enable nginxPHP-FPMとモジュール
Apache Event MPMNginxで動かすためモジュール版PHPは使いません。amazon-linux-extras install php7.3 yum install php-opcache php-apcu php-mbstring php-xml php-xmlrpc php-gd php-pecl-mcrypt php-pecl-imagick-devel php-pecl-imagick php-pecl-zip ImageMagick-devel systemctl enable php-fpmMySQL
RHEL系でデフォルトのMariaDBは使いません。コミュニティのリポジトリからMySQLをインストールします。
yum localinstall https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm yum-config-manager --disable mysql80-community yum-config-manager --enable mysql57-community yum install mysql-community-server systemctl enable mysqldphpMyAdmin
EPELからのyumインストールは依存関係で失敗するため公式サイトのソースからインストールします。
cd /var/www/html/dev.netartz.com/public_html wget https://files.phpmyadmin.net/phpMyAdmin/5.0.2/phpMyAdmin-5.0.2-all-languages.tar.gz tar zxf phpMyAdmin-5.0.2-all-languages.tar.gz rm -f phpMyAdmin-5.0.2-all-languages.tar.gz mv phpMyAdmin-5.0.2-all-languages phpmyadminPostfix
インストールしなくても最初から入っています。有効化しておきます。
systemctl enable postfix
Dovecot
インストールして有効化します。
yum install dovecot systemctl enable dovecotNode.js
EPELのNode.jsは6系と古いので、NodeSourceからLTSな12系をインストールします。
curl -sL https://rpm.nodesource.com/setup_12.x | bash - yum install nodejs有効化して使用する場合は以下を実行しておきます。
systemctl enable nodejs systemctl start nodejs
Docker
ローカルで使用することが多いですが、自分の場合はサーバ側にも必要だったため一応インストールおきます。
不要な場合はインストールしなくてOKです。インストールだけして有効化しない手もあります。
yum install docker
有効化し使用する場合は以下も実行しておきます。
systemctl enable docker systemctl start docker
Fail2ban / Logwatch
ログ監視とセキュリティ対策のためにインストールします。
yum install fail2ban logwatch systemctl enable fail2ban
- 投稿日:2020-04-14T10:27:39+09:00
AWS EC2でサーバを構築 - Amazon Linux 2 準備編
概要
本記事ではAmazon Linux 2の初期設定を行います。
AWS EC2インスタンス作成までが完了している前提です。
ユーザー
ec2-user
でSSHログインして作業します (ダウンロードした鍵ファイルを使用)。文字コードとキーボード
日本の環境に合わせます。
sudo timedatectl set-timezone Asia/Tokyo sudo localectl set-locale LANG=ja_JP.UTF-8 sudo localectl set-keymap jp106設定反映のため一旦切断して再接続します。
反映を確認
設定が正しく反映されているか確認します。
date
以下のように日本時間が日本語で表示されていればOKです。
2020年 4月 14日 火曜日 10:03:39 JST初回アップデート
パッケージのアップデートと再起動を行っておきます。
sudo yum update sudo rebootログイン関連
rootユーザーでSSHログインしたいので鍵ファイルの用意をします。
/root/.ssh/authorized_key
ssh rsa
より前の部分が不要なので削除してから保存します。sshdの設定
パスワード認証を排除します。
/etc/ssh/sshd_config
PermitRootLogin without-passwordsshdを再起動します。
systemctl restart sshd
ec2-user
切断後、root
でSSHログインします (ec2-user
と同じ鍵ファイルを使用)。ユーザー関連
新規ユーザー作成時のデフォルトを設定します。
useradd -D -s /sbin/nologin mkdir -p /etc/skel/Maildir/{new,cur,tmp} chmod -R 700 /etc/skel/Maildir/シェルとVimの設定
- デフォルトのエディタをVimにする
- プロンプトのカラーを変更する
cp
やmv
でワイルドカード*
を使う際、ドットファイルがスルーされないようにする- ターミナルで [Ctrl + S] した際に応答しなくなる問題に対処する
~/.bashrc
alias vi='vim' PS1='\[\033[32m\][\u@\h \W]\$\[\033[0m\] ' export EDITOR=vim shopt -s dotglob stty stop undef設定の反映を行います。
source ~/.bashrc
EPELリポジトリ追加
標準で用意されていないパッケージをインストールするために、EPELリポジトリを使うよう設定します。
amazon-linux-extras install epel
ツール類インストール
今後の作業に必要となる各種ツール類をインストールします。
yum install git curl wget nmap finger htop jwhois
Vim環境設定(例)
個人の好み通りに設定すればOKです。わからなければ以下をコピペして使ってください。
ターミナル内でのコピペが不便なので、行番号は表示していません。
:set nu
、:set nonu
で切り替えられます。~/.vimrc
set nocompatible set encoding=utf-8 set fileencodings=iso-2022-jp,euc-jp,sjis,utf-8 set fileformats=unix,dos,mac set runtimepath+=~/.vim/dein/repos/github.com/Shougo/dein.vim call dein#begin(expand('~/.vim/dein')) call dein#add('Shougo/dein.vim') call dein#add('scrooloose/nerdcommenter') call dein#add('chriskempson/vim-tomorrow-theme') call dein#end() if dein#check_install() call dein#install() endif filetype plugin indent on syntax on autocmd BufRead,BufNewFile /etc/php.ini set syntax=dosini autocmd BufRead,BufNewFile /etc/php-fpm.conf set syntax=dosini autocmd BufRead,BufNewFile /etc/php-fpm.d/*.conf set syntax=dosini if dein#check_install() call dein#install() endif set t_Co=256 colorscheme Tomorrow-Night-Bright set autoindent " set number set nobackup set paste set pastetoggle=<C-e> let NERDSpaceDelims = 1 nmap ,, <Plug>NERDCommenterToggle vmap ,, <Plug>NERDCommenterToggleプラグイン管理ツールのdeinをインストールします。
mkdir -p ~/.vim/dein/repos/github.com/Shougo/dein.vim git clone https://github.com/Shougo/dein.vim.git ~/.vim/dein/repos/github.com/Shougo/dein.vim次回Vim起動時にdeinによるプラグインのインストールが行われます。
- 投稿日:2020-04-14T10:27:39+09:00
AWS EC2でサーバを構築 1 - Amazon Linux 2 準備編
記事一覧
- AWS EC2でサーバを構築 1 - Amazon Linux 2 準備編
- AWS EC2でサーバを構築 2 - 各種インストール編
- AWS EC2でサーバを構築 3 - Apache + Let's Ecnrypt + PHP-FPM編 (Nginxに変更)
- AWS EC2でサーバを構築 4 - Nginx + Let's Ecnrypt + PHP-FPM編 (脆弱性診断「A+」を狙う)
- AWS EC2でサーバを構築 5 - MySQL + phpMyAdmin
- AWS EC2でサーバを構築 6 - PostfixとDovecot (SSL対応とSPAM対策)
- AWS EC2でサーバを構築 7 - セキュリティ対策
概要
本記事ではAmazon Linux 2の初期設定を行います。
ユーザー
ec2-user
でSSHログインして作業します (ダウンロードした鍵ファイルを使用)。文字コードとキーボード
日本の環境に合わせます。
sudo timedatectl set-timezone Asia/Tokyo sudo localectl set-locale LANG=ja_JP.UTF-8 sudo localectl set-keymap jp106設定反映のため一旦切断して再接続します。
反映を確認
設定が正しく反映されているか確認します。
date
以下のように日本時間が日本語で表示されていればOKです。
2020年 4月 14日 火曜日 10:03:39 JST初回アップデート
パッケージのアップデートと再起動を行っておきます。
sudo yum update sudo rebootログイン関連
rootユーザーでSSHログインしたいので鍵ファイルの用意をします。
/root/.ssh/authorized_key
ssh rsa
より前の部分が不要なので削除してから保存します。sshdの設定
パスワード認証を排除します。
/etc/ssh/sshd_config
PermitRootLogin without-passwordsshdを再起動します。
systemctl restart sshd
ec2-user
切断後、root
でSSHログインします (ec2-user
と同じ鍵ファイルを使用)。ユーザー関連
新規ユーザー作成時のデフォルトを設定します。
useradd -D -s /sbin/nologin mkdir -p /etc/skel/Maildir/{new,cur,tmp} chmod -R 700 /etc/skel/Maildir/シェルとVimの設定
- デフォルトのエディタをVimにする
- プロンプトのカラーを変更する
cp
やmv
でワイルドカード*
を使う際、ドットファイルがスルーされないようにする- ターミナルで [Ctrl + S] した際に応答しなくなる問題に対処する
~/.bashrc
alias vi='vim' PS1='\[\033[32m\][\u@\h \W]\$\[\033[0m\] ' export EDITOR=vim shopt -s dotglob stty stop undef設定の反映を行います。
source ~/.bashrc
EPELリポジトリ追加
標準で用意されていないパッケージをインストールするために、EPELリポジトリを使うよう設定します。
amazon-linux-extras install epel
ツール類インストール
今後の作業に必要となる各種ツール類をインストールします。
yum install git curl wget nmap finger htop jwhois
Vim環境設定(例)
個人の好み通りに設定すればOKです。わからなければ以下をコピペして使ってください。
ターミナル内でのコピペが不便なので、行番号は表示していません。
:set nu
、:set nonu
で切り替えられます。~/.vimrc
set nocompatible set encoding=utf-8 set fileencodings=iso-2022-jp,euc-jp,sjis,utf-8 set fileformats=unix,dos,mac set runtimepath+=~/.vim/dein/repos/github.com/Shougo/dein.vim call dein#begin(expand('~/.vim/dein')) call dein#add('Shougo/dein.vim') call dein#add('scrooloose/nerdcommenter') call dein#add('chriskempson/vim-tomorrow-theme') call dein#end() if dein#check_install() call dein#install() endif filetype plugin indent on syntax on autocmd BufRead,BufNewFile /etc/php.ini set syntax=dosini autocmd BufRead,BufNewFile /etc/php-fpm.conf set syntax=dosini autocmd BufRead,BufNewFile /etc/php-fpm.d/*.conf set syntax=dosini if dein#check_install() call dein#install() endif set t_Co=256 colorscheme Tomorrow-Night-Bright set autoindent " set number set nobackup set paste set pastetoggle=<C-e> let NERDSpaceDelims = 1 nmap ,, <Plug>NERDCommenterToggle vmap ,, <Plug>NERDCommenterToggleプラグイン管理ツールのdeinをインストールします。
mkdir -p ~/.vim/dein/repos/github.com/Shougo/dein.vim git clone https://github.com/Shougo/dein.vim.git ~/.vim/dein/repos/github.com/Shougo/dein.vim次回Vim起動時にdeinによるプラグインのインストールが行われます。