souichirou のすべての投稿

[PHP]重要な文字列を暗号化して保管し、利用するときは復元する方法(OpenSSL使用)

PHP

mcrypt関数はPHP7.1.x系より非推奨、PHP7.2.x系より廃止となりましたので現在推奨となっている『OpenSSL関数』で文字列の暗号化と復元をする方法を紹介します。

重要な個人情報をフォーム等から受取り、データベースへ保存する際には気をつけなければいけません
社内のシステムであってもダンプデータを持ち出されれば個人情報が丸見えの状態で取り出すことができてしまいます

パスワードなんかは確認の際に利用するだけなのでハッシュ化して、保存されている値とPOSTされた値を比べればいいので復元する必要はありませんが、顧客の住所などを保存したい場合は後で再利用するので復元できる形で保存する必要がでてきます

PHPを使ってMySQLなどのデータベースに保存する方法をご紹介します

使用する関数は OpenSSL

まずは暗号化する処理です

ここで暗号化は完了ですが、復元させるためにデータベースに保存する項目はIVキーと暗号化されたデータとなります
IVキーとは『単に暗号化ルーチンに異なる初期値を与えるためだけのもの』ということで、一緒に保存して構いません
重要なのはパスフレーズの方です。パスフレーズまで漏れると誰でも復元できてしまうようになります

今回はPHPの内部にパスフレーズを記述していますが、FTPサーバから不正侵入された場合にはファイルを直接参照されてしまいますので、サーバ内の外部からアクセスできない場所に文字列を保存したファイルを置いておき、includeなどで呼び出した方がセキュリティとしては高まります
例)
/var/etc/security/hoge など

データベースに保存するのはIVキーと暗号化されたデータになりますが、この2つの値はどちらともバイナリデータです
保存するにはカラムのデータ形式をバイナリに指定していてもいいですが、バイナリデータとして保存するとSQLで抽出した際の視認性が好きじゃないということでBase64でエンコードした値を保存するようにしています

バイナリーだとこんな感じに見えるのが
M�(���z��53�a

Bace64でエンコードすると
TaB/KMTUA/Z66scGNTMWsGE8RdrSgPwraNRtcWRLmCQ=

みたいになります

Base64でエンコードしたデータはデコードでそのまま復元できますし、カラムの形式もVARCHAR型で構いませんので難しいことを考えなくてもよくなります

Base64にエンコードするには

この値をデータベースに保存すれば暗号化処理の完成です

続いては復元の方法です

パスフレーズの設定を細かくするかどうかにもよりますが、そんなに複雑な処理もなく重要な情報を復元できる形で暗号化できますので、万が一に備えて暗号化を進めていくのもいいかもしれません

【JavaScript】メールアドレスが収集されるのを防ぐ

WEBサイトにメールアドレスを素のままで記載するとSPAMメールのアドレス収集ロボットに集められてしまうので色々と工夫しますよね。
迷惑メールが増えてしまうと大事なメールを見落としていまう確率があがってしまいます。

対策してよくあるのは
・@マークを全角にする
・@マークをHTMLエンティティ化(【@】にする)
・メールアドレス自体を画像にして表示する

どれも利用者に不便をかけたり、煩わしかったりします。
画像以外はクローラーが対策をすれば収集するのは簡単ですしね。

『クリックしたときにメールソフトを起動させてすぐにメールが送れるようにしたい。しかも、あんまり複雑にしたくない。』

そんな場合にJavaScriptを使ってサイトソースにメールアドレスを残さない方法です。

【用意するもの】

・jQuery
 普通にJavaScriptだけでもできますが、他の部分の処理をjQuery使っているのにここだけ記述が違うのもメンテナンスが悪いので
・メールアドレスをbase64に変換
 今回の仕組みはbase64にした値を元にメールアドレスを戻して表示します

【記述】

メールアドレス例:(わざと大文字化と半角スペースを空けています)
test-info @ exsample.com

base64形式にエンコード後:
dGVzdC1pbmZvIEAgZXhzYW1wbGUuY29t

[HTML]

[JavaScript]

メールアドレスを表示させるアンカータグの記述にあるdata属性(data-obfuscatekey)にbase64形式にエンコードしたアドレスを入れます。
JavaScriptで該当の要素にあるdata属性(data-obfuscatekey)の値を取得して、atob関数でbase64形式でエンコードされたデータの文字列をデコードします。

”bWFpbHRvOg==”という文字列をデコードすると”mailto:”となっているので、アンカータグ内のリンク先がattr関数で”mailto:test-info @ exsample.com”と置き換えられます。

最後にリンクテキストにデコードしたメールアドレスを書き換えています。

ソースコードを見てもbase64形式にエンコードされた文字列しか残っていませんのでクローラーもメールアドレスとは判別するのは難しいでしょう。

data属性の値をデコードしてメールアドレス形式だったら収集するクローラーが出てくる可能性もあります。
より複雑にしたい場合はメールアドレスを分割し、data属性を複数持たせておいてデコードしたものを繋ぎ合わせればいいだけです。

PHPで手軽にWEBサービスの死活監視&エラー時にChatWorkにメッセージを投稿する

htaccess

WEBサーバの死活監視の1つとして有効的なのがURLチェックです。

PINGコマンドでドメイン名を指定してもサーバ側(FWなども含む)でPINGに応答しないように設定していると稼動しているのに応答がないといった状況になります。

1番正確に判定しやすいのが、実際にURLにアクセスして目視する。
ですけど、1日に何度も目視なんてしてられませんから自動で監視してくれるサービスもあります。

大きな企業になれば自動で監視してくれるサービスにも費用を出して万全の体制がとれますが、あまりお金を掛けられない会社では担当者が毎日WEBサイトにアクセスして死活監視を目視しているということがあります。

また、監視サービスを利用していても、エラーが発生した場合に複数人にEメールメッセージは送信されているが「誰か対応するだろう」といった対応漏れが発生してしまうことも起こります。

Eメールだと他のメールに埋もれて見落としてしまったり、自動メール配信なので迷惑メールとして判定されてしまったりとリスクがあります。

そこで、お金をかけずに複数人でも進捗が把握できるようにチャットワーク(https://go.chatwork.com/ja/)を利用する仕組みを考えました。

【用意するもの】

・常時稼動しているサーバ(インターネット疎通あり)
・PHP7.x系
・Cron
・チャットワークのアカウント(API専用で用意した方がいいです)
 ※チャットワークについてはこちら(https://go.chatwork.com/ja/)

【確認できること】

ブラウザからHTTP(S)接続してページが見えるかどうか

HTTPアクセスを強制リダイレクトでHTTPSにしているなどアクセス左記がリダイレクトされていてもHTTPステータスコード302が返ってきますので正常稼動していると判定します。

SSL証明書の失効、設定ミスの場合はアクセスが拒否されますのでエラーとして判定されます。

ログイン画面が表示されるものは正常稼動と判定されますが、Basic認証の場合はエラーとして判定されます。

グローバルIPでHTTP接続が可能ならば正常として判定されます。

サーバの応答が異常に遅い場合(応答の状態にもよりけり)もエラー判定されます。

【スクリプト】

注意点
・監視したいサービス名称を決める際は2バイト文字・半角カナ・記号等は避けてください。サーバ側の設定によっては文字化けファイル名が生成されて全体にエラーを及ぼす可能性があります
・エラーが発生した日時を記録するファイルを生成しますので、ファイルの設置場所には書き込み権限が必要です
・Cronを利用する場合はサーバに余分な負荷をかけないように間隔を調整してください
・チャットワークのAPIは5分間に1000回までですでの余分な動作の実行はしないように調整してください
・チャットワークのルームIDとは対象チャットルームURL(www.chatwork.com/#!rid0000000)の /#!rid 以降の数字です
・.htaccessで404Not Foundを正常なページへ強制リダイレクトさせている場合は正規に存在するファイル(テキストファイルなど)を指定しましょう

必ず書き換えが必要なのは最初の項目の $target と $cwRoomId と $cwTokenCode の部分です。
サーバは稼動しているけども負荷が高くて応答に時間がかかっている場合も分かるように応答時間をシビアに設定しています。
応答時間をゆるくしたい場合は $curlOptions の項目を変更してください。
エラーが発生して対応するまでには時間が必要ですので、何度もお知らせがくるのが嫌な場合は $compTime の値を変更して下さい。

任意のファイル名でスクリプトを設置したらブラウザからアクセスしてみてください。
://example.com/hoge.php

全てが正常であれば架空のサブドメインを追加してみてください。
エラーがでてチャットワークで指定したチャットルームにメッセージが届けば成功です。

【cronの設定】

あまり頻繁にすると監視先のサーバに負担をかけてしまうので環境に合わせて調整しましょう

JavaScriptで数値の取り扱いに気をつける

JavaScript

TwitterのAPIを使ってデータ取得し、JavaScript経由で処理をしているときにはまった話です。

特例の文字列に関するTwitterユーザーをユーザー検索APIで叩いて数名の候補を一覧表示して、その中から目的にあった1人のユーザーをリスト化していくという作業をしていました。

使用API:GET users/search
詳細:https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-search

Twitterユーザーを一意にする情報としては”screen_name”もしくは”id”
本来の目的からいくと”screen_name”が欲しかったので、この時点で取得した”screen_name”を保存していこうかと考えていましたが、Twitterのアカウントは使われていなければ自由に取得することが可能なため、悪意のある取得であったり、偶然のバッティングが発生することもあります。

これから将来的には、必要性の高い”screen_name”は入替の可能性も出てくるかもしれません。
そこで、書き換えの可能性があり得る”screen_name”だけを取得するよりもユーザー”id”を基準として取得しようと考えたわけです。

やっぱりデータの一意性はID(数値)だね。ということで

JavaScript経由でデータベースに保存しようとしていたので、文字列である”screen_name”にエスケープが必要な文字が入っていると面倒だなとも考えたのも1つです。
(DBに保存するまでデコード、エンコードが繰り返されるので)

ユーザーIDだけ取得してJavaScript経由でPHPスクリプトに渡し、DBに保存する手前で再度API(GET users/lookup)を叩いて”screen_name”を取得するといった流れで作りこみました。

送信ボタンにセットした値はこんな感じです。

すいすいと処理を進めていっていると、DB保存前の段階で”screen_name”が取得できなかった場合のエラー処理コードが表示されました。
とりあえず1件飛ばして進めていると、また同じエラーコードが表示されました。

IDが取得できていなければ先に進めないようにしていたし、ソース表示してもちゃんとIDがデータとして渡されるようになっている。
エラーがでている対象をよく見てみると「IDの桁が多い」ということが分かりました。

JavaScriptは『IEEE754』という規格に従って内部的に数値を『64ビット倍精度』で保管しています。
うまい表現が見つからないですが、処理できる値に限界があるって感じです。

まさかTwitterのIDがそこを超えちゃってるだなんて・・・
数値だけでIDが構成されているので桁数が増えていっているのでしょう。

限界を超えてしまったものをどうするかというと、toFixed(0)を使えばうまく処理できました。

getID.toFixed(0);

こうすれば数値としてPHPスクリプトに渡して再度APIを叩けば正確な”screen_name”を取得することができます。

しかし、IDの構成が数値だけから英数字の組み合わせに変わってしまうと思わぬ落とし穴にまたはまってしまうので、
送信ボタン自体に埋め込む時点で文字列に変更しました。

文字列として最初から処理してしまえばTwitter側の仕様が変わっても問題ありません。
これで解決

JavaScriptで演算するときは数値の変化に気をつけていましたが、受け渡しでも気をつけておかなければならないことを見落としていました。

結論
JavaScriptを使うときの数値は本当に面倒だ

[PHP]iTunesライブラリのXMLファイルから必要な項目だけをCSVにしたい

PHP

iTunesのデータをCSVにしたり、データベースに突っ込みたいと考えてみたものの、iTunesから吐き出したライブラリのXMLファイルはちょっと特殊です。
PHPを使って加工したいと考えても創意工夫が必要になってきます。

世の中には同じようなことを考えている人はいるもので、Githubに加工用スクリプトをあげてくれている人がいるのですが、エラーがでてうまくいかない。
エラーの内容を見ながら修正しても、また次に別のエラーが出たりと心が折れます。

そもそも、エラーが出る原因としてはiTunesライブラリのXMLファイルをすんなりと処理できないのが原因です。

楽曲の詳細が入っている部分を抜き出してみました。
※楽曲によって項目はバラバラです。

<key>の部分は項目だというのは分かります。
その次が値になるのですが、項目にあわせてデータ型が指定してあるんです。
テキスト ・・・ <string>hoge</string>
数値 ・・・ <integer>hoge</integer>
日付 ・・・ <date>hoge</date>

他には <true/>だの<false/>だのあります。

なので、simplexml_load_file()を使ってXMLファイルを配列にすると、値として1つのくくりで取得したいのにそれぞれのデータ型に合わせた配列ができてしまいます。
しかもXMLファイルにはiTunesで値を入れている項目しか出力されませんので○個目は必ずこの項目になるという確約がありません。

だからこそ有志の方がGithubにスクリプトをあげていてくれたりするのですがエラーがでるんです・・・だけどデータを取得したいんです。

というわけで、ちょっと力技で取得します。

XMLファイルの中身を修正してから取り込みます。
・スポット的にするならテキストエディタを使って置換
・定期的にしたいならばシェルスクリプトを作ってsedコマンドで置換

置換する文字列は

下記ならば
・string>
・interger>
・date>

value> へ

下記ならば
・<true/>
・<false/>

<value></value> へ

XMLファイルの加工が終わったらサーバへアップロードします。
例)iTunes.xml

CSVに吐き出すPHPスクリプトは

項目を変更したい場合はヘッダーと取得行の3箇所を修正します。
CSV出力ではなくてデータベースへINSERTしたい場合は適宜書き換えてください。

置換作業という手作業は入りますが、iTunes側に変更があった時にも対応しやすくなるかと思います。

CSVファイルのデータが空(””,””,””,””,””,””,””,””)になっている場合はデータ項目の置換漏れや私の環境では見つけれていない<hoge>という別な要素名がXMLファイル内にあるのが原因ですので探してください。

JavaScriptでスマホやタブレットを判定してパラメータ付でリダイレクトする方法

JavaScript

WEBサイトをレスポンシブにしたいときはスタイルシートで切り替えますが、そんなこと言ってもPCはPC用、スマホはスマホ用、タブレットはタブレット用でページを変えたい事案があります。

但し、それぞれのページを個別に分けても自動で選んでくれる訳ではないので、JavaScriptを使ってページ内に仕込みます。
ただ、パラメーターで動的にページの内容を変更したい時やアクセス解析に利用したい場合に単純にリダイレクトしてしまうとパラメーターが消えてしまうので、今回はパラメーター付きでリダイレクトさせます。

例)
exsample.com/?a=abc

スマホ用 ・・・ exsample.com/sp/?a=abc
タブレット用 ・・・ exsample.com/tab/?a=abc

【作成】

これをPC版に相対するページとしてスマホ用、タブレット用として用意しているページに埋め込みます。
スマホできたらスマホ版へ、タブレットできたらタブレット版へとリダイレクト。しかもパラメータ付です。
もちろんスマホ版だけ切り分けたければスマホだけリダイレクトさせればいいだけです。

レスポンシブを作っているよりもスマホ版を別で作ったほうがいいと思う今日この頃。

Excel(エクセル)がダブルクリックしても開かない時の対処法 – その3

catch_office

エクセルファイルが開かない場合の対処法を過去2回後紹介しました。

・エクセルやワードファイルがダブルクリックしても開かない時の対処法
・Excel(エクセル)がダブルクリックしても開かない時の対処法 – その2

3回目となる今回は『開いているのに開いているように見えない』という状態です

開いているように見えないですから『開かない』が正解ですね


まずは状況から

こんなエクセルファイルがあります
エクセルが開かない01

このファイルがこんな風になっている状況です
エクセルが開かない02


普通に見えいてるエクセルファイルを閉じてエクセル本体だけにした場合の画像も用意してみました
エクセルが開かない03

もう1度、エクセルファイルが開いていないように見えている画像です
エクセルが開かない04

違いが全く分かりません
『開いていない』としか見えようがありません。

【復旧】

では原因と正常に表示させる方法です

開けていないと思ってしまうファイルを開いた状態でリボンを確認。
[表示]を開きます。
エクセルファイルが開かない05

[ウィンドウ]に注目してください
エクセルファイルが開かない06
ウィンドウの部分で【再表示】が表示され、【表示しない】がグレーになっていればここが原因です。

【再表示】クリックすると
エクセルファイルが開かない07
開いているファイル名が選択された状態でダイアログが表示されますのでOKを押下します。
すると本来の正常な姿でファイルの中身が確認できるようになります。

リボンにある【ウィンドウ枠の固定】機能の横に【表示しない】があるので押し間違えた可能性が高いです。
ウィンドウ枠の固定機能は現在選択しているシートに対しての機能なので、シートを非表示にさせそうな機能ですが実際はブック全体に影響する機能になっています。
故意に操作していなければ思いもよりませんし、こういう機能があることをどれくらいの人が知っているのでしょうか。

再表示する際のダイアログに『表示するブック』とあるのだからウィンドウじゃなくてブックにすればいいのにな

開かない原因は他にもあります。
この対処法でもダメな場合は他のページも参照してみてください
エクセルやワードファイルがダブルクリックしても開かない時の対処法
エクセルがダブルクリックしても開かない時の対処法 – その2

MacとWindowsでUSBメモリを使っていると謎のフォルダが作成される訳

Apple

exFATでフォーマットしたUSBメモリを使えばWindowsとMacでファイルのやり取りがスムーズにできます。
MacでUSBメモリを使った後にWindowsに差し込むと変なフォルダができています。

・.fseventsd
・.Spotlight-V100

Macで使ったUSBメモリ

パッと見の名前からは目的が想像つかないので『ウイルス系?』と思った方も多いはず。
しかし、このフォルダは安全です。

【fseventsd】
Macのファイルシステムのイベントログが関係しています。
File system events と英語で書けば、【fseventsd】が「あぁ、そういうことね」と分かるかと思います。

【Spotlight-V100】
上の意味が分かると「あぁ、Spotlight関係ね」と分かるかと思います。
Spotlightがファイルをサーチするための記録みたいなものです。

何度もやり取りをしていると記録が溜まってきて、内部のファイル容量が増えてくるようなので両方とも目障りであれば消してしまっても構いません。

USBメモリを使って人とやり取りすることもあるので、改めて使う場合は必ずフォーマットしてから使うようにしています。

[AWS]営業資料を全支店で共有するためにS3とCloudFrontをIPアドレス制限で活用する方法

Amazon Web Services

会社の資料としては、営業用・システム用など部署によってエクセル・ワード・パワーポイント・PDF・画像・動画などなど様々な種類の資料が溢れいています。
システム系の資料であれば外部から閲覧する必要もないので全社的なファイルサーバに入れておけば各支店のシステム担当者が同じ資料を閲覧することができます。

営業用の資料となると、事務処理に関するものはファイルサーバで管理は十分ですが、商品の変更や新発売、キャンペーンなどによってカタログの入替が必要だったり、iPadを活用していればプレゼンテーション用の動画の差し替えが必要だったりと煩雑になってきます。

しかも各支店の全営業員へとなると配布するのも大変になります。
そこで最近は営業社員向けにポータルサイトを作成して資料を管理する方法も増えてきていますが、ファイルサーバの中のファイルとポータルサイト側に載せたファイルが混在しちゃいませんか?

「新しい資料ができたから営業へ配布しないと」

「ポータルサイトの新着を更新して」

あっ、ファイルサーバにファイルアップするの忘れてた・・・

ポータルサイトはあくまでも営業社員のみの資料を掲載する目的ですので、会社としての資料はファイルサーバ側で管理できることが望ましいのに対して、『早く配布しないといけない』という意識の方が強くなるのでプライオリティーの高いはずのファイル管理が疎かになってしまいます。

そこで、ファイル管理にもファイル配信にも使える方法を考えてみました。

まずは、AWSのS3を利用してファイルを管理します。
ファイルサーバを自社内で持つとなると、サーバ構築はもちろんバックアップや回線、残容量の管理の問題もあります。
数年間経ってファイルサーバの中を見てみると【作ってから再利用していない】ってファイル多くないですか?振り返れば必要ないけど、それでも取っておきたいファイルなんです。
容量の問題があるから○年間使用がなければ強制的に消すってされても困るんです。ってありませんか?
カメラの性能が上がった分だけファイルの容量も大きくなってきています。ピントがずれた使えない写真でも・・・

だからこそAWSのS3をファイルサーバとして活用するメリットが高くなってきています。
そこでS3を活用し、社内ネットワークからはファイルサーバ、社外のタブレットから(VPN経由)はコンテンツ配信として利用することでファイルの管理の一元化、システム負担を減らしたいと考えました。
ファイルの中には機密情報もあるのでもちろんIP制限は必須です。

S3だけだと動画の配信が厳しい場合もあり、CloudFrontも利用したいと考えていますのでこちらは後述します。

S3にIP制限を設定する

1.バケットを作成します

2.S3が公開設定になっていないか確認します

【Static website hosting】が無効になっていることを必ず確認しておいてください。
S3はHTTPサーバとしても機能します。有効になっていると全世界に向けてファイルを配信してしまうことになるので気をつけましょう。

3.テスト用のファイルをS3のバケットへ設置します

適当にテキスト文字を打ち込んだファイルをアップロードします。

4.アップロードしたファイルのプロパティでファイルへのリンク先を確認
まだこの時点ではアクセスが出来ないようになっていますが、S3にあるファイルを直接閲覧できるリンクが発行されています。

5.リンク先にアクセスしてアクセスできないことを確認する
この時点でファイルの中身が見えるとバケットが全公開になっていということになります。ファイルサーバとしては致命的な設定ミスが生じています。

6.アクセス権限のバケットポリシーを設定する
許可したIPアドレスでしかバケットに接続できないように設定します。
設定するには記述を書かないといけないのですが、AWSではその記述を生成してくれる画面があります。
AWS Policy Generator
http://awspolicygen.s3.amazonaws.com/policygen.html

必要な項目を埋めていきます

Select Type of Policy:S3 Bucket Policy
Effect:Allow
principal:*
AWS Service:Amazon S3
Actions:All Actions(‘*’)
ARN:arn:aws:s3:::バケット名/*

Add Condition(Option)をクリックして
Condition:IpAddress
Key:SourceIp
Value:許可したいIPアドレス

ボタンになった【Add Condition】をクリックして設定を保存させて【Add Statement】をクリック

生成されるコードは

こんな感じ

このコードをアクセス権限のバケットポリシーに保存します。

さあ、これで先ほどのテキストファイルにアクセスして見てください。
正常にアクセスできれば成功です。

成功したら先ほどのバケットポリシーのIPアドレスを書き換えてみてください。
書き換えてアクセス拒否になれば指定されたIPアドレス以外ではアクセスできないことがきちんと確認できました。

各支店のIPアドレスを設定に追加していけば各拠点からしかアクセスできないS3バケット(ファイルサーバ)の出来上がりです。
新しいファイルが出来上がり、配布が必要になった場合にはファイルのリンクをポータルへ貼り付けてしまえばユーザーはクリックしてダウンロードが可能ですので、勝手にファイルを書き換えられることもなければファイルサーバとポータルサイト側でファイルの整合性がとれなくなることもなくなります。

S3から動画の配信をさせることも可能ですが、動画ファイルだとどうしてもファイル容量が大きくなってしまいます。動画ファイルだけでなくパワーポイントやPDFファイルなどでも容量が大きなファイルだと客先でプレゼンしようと思ってダウンロードしたくてもS3のリージョンは東京ですので遠方地だと回線の問題もありダウンロードに時間が掛かってしまいます。

そこで、ファイル容量が大きなファイル(ファイル自体の更新が頻繁に実施されないファイル)はCloudFrontを使ってCDN配信(Content Delivery Network:コンテンツ・デリバリ・ネットワーク)させる方がメリットがあります。

但し、CloudFrontを使用するとそれこそ世界中にファイルのキャッシュが広がってしまうので、こちらもIPアドレスで制限を設けてしまいましょう。

CloudFrontでIP制限をする

1.まずはCloudFrontのディストリビューションを作成します。

ここでは作り方は割愛します。

2.ディストリビューションを作ったらプロパティを見てみましょう

【AWS WAF Web ACL】の項目に何も設定されていませんね。
AWSから提供されているWAFの機能を使ってIP制限を実施します。

3.WAFの設定画面に移動する
セキュリティ、アイデンティティ、コンプライアンスの項目にある【WAF & Shield】の項目になります。

ここでWAF用の【Web ACL(ウェブアクセスコントロールリスト)】を作成しますが、CloudFrontを使うときに気をつけなければいけないのが【Filter】の項目です。
CloudFrontはリージョン設定はありませんので【Global】に切り替える必要があります。

リージョンを切り替えたら次に進んで項目を埋めていきます。
このときに、先ほどCloudFrontに作成したディストリビューションを設定します。(後でも設定・変更は可能です。)

次へ進むと、何を基準としてコントロールするかの項目が出てきます。
ここではIPを指定したいので【IP match conditions】の【Create condition】選択します。

許可したいIPアドレスを登録していきます。

登録を完了させると【IP match conditions】の部分に設定した名称が表示されているのが確認できます。

次へ進むと
先ほど作成したWeb ACL(allow_ip_list)を適応させるルールを作ることになります。

ルールの名称を決めて
下部の【Add conditions】へうつります。

先ほど作成したWeb ACL(allow_ip_list)のIPアドレスを許可したいので下記のように設定します。

・does
 下記の設定を元に制御する

・originate from an IP address in
 IPアドレスに対して

・allow_ip_list
 指定するIPアドレスの入ったWeb ACL

ルールを新規登録したら前の画面に戻るので、そのルールに対して許可するのか拒否するのかの挙動を決めます。

【If a request matches all of the conditions in a rule, take the corresponding action】の項目は、『ルールに適応した場合はどうしますか?』という内容なので、【Allow】を選択します。
※ここは複数のルールを適用することもできます。

【If a request doesn’t match any rules, take the default action】は『ルールに適応しなかったらどうするの?』という内容なので【Block all requests that don’t match any rules】を選択します。

ルール適用の最後の確認画面にたどり着きました。
【AWS resources using this web ACL】の部分に、IPアドレスでアクセス制限をしたいCloudFrontのディストリビューションがきちんと設定できているか確認します。

Web ACLsが増えているか最初の画面で確認します。

最後にCloudFrontの画面に戻り、WAF設定を適用したいディストリビューションのプロパティを確認してみてください

【AWS WAF Web ACL】の項目に作成したACLの名前が入っていますね。

これで設定は完了です。
CloudFrontのディストリビューションに割り当てられたドメインを元にS3に設置したファイルへアクセスすれば許可したIPアドレスからのみ閲覧が可能となります。
しかし、気をつけないといけないのがCloudFrontがキャッシュを広げるまで時間が掛かります。
ファイル自体がまだキャッシュされていないときはS3に該当するファイルを取得しにいく仕組みなので、今度はS3側でCloudFrontの許可をしていないことになりアクセスが拒否されます。

キャッシュが広がるのを待っていると至急の資料の配布が遅くなってしまうので、S3のバケットへCloudFrontからのアクセスを許可する設定を追加します。
CloudFrontの設定からワンクリックでバケットポリシーを追加できるので難しくありません。

CloudFrontの該当ディストリビューションのOriginの編集モードへ入ります。
【Grant Read Permissions on Bucket】の項目の『Yes, Update Bucket Policy』を選択して編集を完了させればバケットポリシーにCloudFrontからのアクセス許可権限が追加されます。

バケットポリシーを見てみると下記のように追加されているのが分かります。

これで正常にアクセスできるのが確認できます。
WAFで制御できているか確認するには、Web ACLに設定したIPアドレスを架空のIPアドレスに変更してみてください。

下記のような画面がでれば許可されたIPアドレスではないのでWAFでブロックされたことが分かります。

社内用のサービスとしてクラウドを利用する場合はなんといっても大切な情報がインターネット上に流出しないかという懸念が一番大きいかと思います。
もちろん設定次第では思わぬ落とし穴がありますが、細かな設定ができるAWSはかなり便利な使い方ができます。

全部ダメ! or 細かく設定したらいいよ

と、うまく設定できていないときは迷宮入りクラスですが、逆に言えば『ちょっとしたミスでも大きな事故が起こりにくい』と言えます。(大きな事故とは情報流出のことで社内的には大惨事になってしまいますが・・・)

固定IPアドレスを設定しているのにipconfigを叩くと別のIPアドレスが表示される場合の原因

Windows

自宅でも社内でも同じなのですが、IPアドレスを固定にして1台ずつ設定をしているとします。

ローカル内で設定するプライベートアドレスをといえば

  • 10.0.0.0~10.255.255.255
  • 172.16.0.0~172.32.255.255
  • 192.168.0.0~192.168.255.255

がほとんど使われています。

こういったIPアドレス運用でたまに発生してしまう現象です。

IPアドレスを 10.0.1.101 と設定している端末があるとします。
ある日、PCを起動するとインターネットに繋がらない・ファイルサーバに繋がらないといった現象が起きました。

こういった時はネットワークの障害が考えられるので最初に確認するべきは、対象端末のLANケーブルがちゃんと差し込まれているかですね。
端末の使用者がちょっと本体を動かしたつもりでもLANケーブルが抜けてしまったりなんかはたまーにありますので先に確認しておきましょう。
次に確認するのはネットワークの設定です。
※セグメント全体で同じような減少がおこったらルーター等を先に疑うべきでしょう。

ネットワークのプロパティから
【インターネット プロトコル バージョン4(TCP/IPv4)のプロパティ】
を確認してみます。

決まりどおりの設定になっていますね。
でもネットワークに繋がらない。。。

この時点でルーターなどの確認にいってしまうと迷宮に入り込んでしまいます。
最小限の手順で解決させていくためにも先にするのは本当にパソコンのIPアドレスの設定が間違っていないかの確認です。

ネットワークのアダプタ設定から見た場合、そもそも間違っていないと思っているから設定ミスに気がつきにくかったりしますので、オススメはコマンドプロンプトでも確認することです。

コマンドプロンプトを立ち上げて ipconfig と打ち込みます。

設定しているはずの 10.0.1.101 ではなく

169.254.xxx.xxx

となっていますね。
サブネットマスクも 255.255.255.0 ではなく 255.255.0.0 になっています。

この原因は・・・

原因

IPアドレスが他の端末と競合している。

パソコンかもしれませんしサーバーやプリンタ、ネットワーク機器かもしれません。
固定IPとDHCPとを混在させている場合に切り分けができていないとDHCPで割り振られた他の端末と競合してしまっているかも知れません。

XPなんかは『他にも同じIPアドレスが使われているものが存在するよ』みたいなメッセージを表示してくれていたと思うんですが、今のWindowsはAPIPA(Automatic Private IP Addressing、エーピーアイピーエー)という機能が働いて別のネットワーク構成を設定してくれる仕組みになっています。

簡単に言うとDHCPみたいな機能をWindows側がやってくれるのです。
競合していると別のネットワーク設定に内部的に変更してくれます。何も言わずに

ネットワーク構成が強制的に変わることで既存のネットワーク内に繋がらなくなるため、サーバとIPアドレスが競合してしまってサーバの機能を止めてしまい社内業務を停止させるなんてことは起きないようになるのでいいことです。
元はといえば競合してしまう設定をした管理の悪さが起因だと分かってはいますが

でも何も言わないって・・・


競合していることが分かれば他の端末を使ってpingで対象IPアドレスを叩けば該当する端末が存在することも確認できます。
確認できればあとは探し出すか、他のIPアドレスに振り直すだけです。

ただし、ファイヤーウォールのエコー要求を無効にしていればpingコマンドで叩いても応答がありませんので他のIPアドレスに振りな直そうにもカオスに陥ります。
※エコー要求を許可するかは企業のセキュリティポリシーにもよるので簡単に許可できるものでもありませんしね。

何事も管理が大事です。