KITA Eng.

北海道でサーバー技術者として歩み出したひとが綴るblog。

Cloud Garageの「接続許可(詳細設定)」でサーバーを守る

特定非営利活動法人Kacotamの内部用ポータルシステムの開発・運用等を担当させてもらっています(2017年5月からシステム稼働)。 このシステムのインフラ部分として、2017年9月からCloud Garage Dev Assist Program (DAP)での支援を受けています。 2017年7月から始まった新しいクラウドサーバーのサービスですが、これまで大きな障害等なく快適に使えています。

サービス開始当初は最小限の機能でのスタートでしたが、ついにCloud Garageにもインスタンス管理画面上で任意のポートに対する接続許可設定ができるようになっていました。

2018.10.05 新機能追加のお知らせ(接続許可 詳細設定)
従来のCloudGarageでは、未使用ポートへの不正アクセス防止のために、特定の開放ポートを選択して制限する方法をとっていましたが、今回のアップデートにより任意のプロトコル、ポート番号、送信元IPアドレスを指定できるようになりました。コントロールパネル上での簡単な操作で、より高いセキュリティレベルでの運用が可能になりましたので、ぜひご活用ください。 cloudgarage.jp

この機能ができるまでは、SSHの接続ポートを標準の22から変更している場合や、特定のIPからのみ全ポートを許可するなどをしたい場合は、インスタンスの管理画面上では、「全解放」にして、インスタンス内でiptablesなどを使って設定する必要がありました。

サーバー上での設定は、インスタンス作成直後や設定ミスで漏れが発生することもあるので、管理画面上からできるのは◎です

早速設定してみた

Cloud Garageのコントロールパネルはシンプルな作りなので、すぐに見つけられるような気がしますが、一応画面付きで順を追って紹介します。 一部、インスタンスの情報やIPアドレスの部分はマスクしています。

1. 変更するインスタンスの詳細画面を表示する

Cloud Garageのログイン画面からログインすると最初に表示される、インスタンスの一覧表示画面から、接続許可設定を変更したいインスタンス名をクリックする。 f:id:kacchan822:20181019133436p:plain

2. 接続許可設定のダイアログを表示する

インスタンス詳細画面の右下にある、「接続許可設定」の鉛筆アイコンをクリックする。 f:id:kacchan822:20181019133439p:plain

3. 接続許可「詳細設定」を行う

「かんたん設定」の範囲以外のポートを空けていたので、「全解放」のラジオボタンが選択されていました。 f:id:kacchan822:20181019133441p:plain

中央にある「詳細設定」のラジオボタンをクリックすると、ルールを入力できるようになります。
親切に説明があるように、ポートを範囲で指定したり、IPアドレスをブロック単位で指定することもできます。 f:id:kacchan822:20181019133444p:plain

入力ができたら、「更新」ボタンをクリックして保存します。

4. インスタンスの詳細画面で確認

正常に設定が完了すると、インスタンスの詳細画面の右下にある「接続許可設定」の部分に設定内容がリスト表示されています。 f:id:kacchan822:20181019133447p:plain

で、どうなの?

インスタンス内での設定は、iptablesのフロントとして、UFWを利用していて、ブロックしたパケットがあるとログに出るようにしています。ログを見ていると毎日毎日あらゆるところから、開いてもいない22や21、25への接続が来ていました(開いてないからつながりはしないけれど....)。
今回の「接続許可(詳細設定)」の設定後は、UFWのログに記録されるブロックパケットが皆無になりました。

Docker-composeを利用していると、ポートバインドの記述ミスで、UFWでは制限をかけていても、docker側のフォワードの関係でつながってしまう状況が発生してしまうこともあり得ます。
インスタンスに届く前で通信を制限してもらえることで、そういったミスの際のリスクを回避することができるので、ステキです!

(編集後記)

すっかりご無沙汰しておりました。
2017年から特定非営利活動法人Kacotamにて、システム開発室室長の銘を受けていました。
2017年春に、団体WEBページのリニューアル、内部向けポータルサイトの稼働などがあり、わたわたとした1年でした。
これまでは、僕自身を含め、Kacotamの主たる活動の学習支援活動と兼務でのメンバーばかりでしたが、最近開発室専従のメンバーが加わり始めました。
子どもの福祉に関わるNPOで、システム開発室を自前で持っているところはないと思うので、少しでも情報発信して行けたらなと考えています。
(後々専用のTech Blogができるかもですが、)しばらくは、Kita Eng. からお伝えしていきます。関連記事には、Kacotam-Si-Teamのタグをつけるようにしていきます。

Django Class-based views でCSVダウンロードページの実装ではまったこと

公式ドキュメント Outputting CSV with Django | Django documentation | Django とか、GoDjangoの記事 Download CSV files via CSVResponseMixin - GoDjango とかあるからさくっと行けるだろうと思ったら、意外な落とし穴があった。

ダウンロードされるCSVファイルのファイル名をレスポンスヘッダーの"Content-Disposition"に入れてあげるのですが、Chromeさんだと特に何も考えず、

GoDjangoにある以下の書き方で、日本語名でも全く問題なく行ってくれました。

response = HttpResponse(content_type='text/csv')
cd = 'attachment; filename="{0}"'.format(self.get_csv_filename())
response['Content-Disposition'] = cd

が残念ながら、Firefoxさんだとファイル名を受け取ってくれません。 Google先生に問い合わせると、先人がいらっしゃいました(PHPでの実装だけど)。

scientre.hateblo.jp

比較的最近のブラウザでは RFC 2231 形式に対応しているので、通常はこの形式を使えば問題は少ないだろう。

ということなので、 RFC 2231 - MIME Parameter Value and Encoded Word Extensions: Character Sets, Languages, and Continuations を読んだつもりになって、「python rfc2231」とかってググると、 19.1.14. email.utils: 多方面のユーティリティ — Python 3.6.5 ドキュメント 使っとけって出てくるので、使ってみたら無事解決。

たぶん使いまわしがきくであろうMixiにしておいてみた。

UTF-8CSVをうまくExcelさんに読んでもらうためには、BOM付UTF-8にしないといけないらしく、それでも微妙にはまった(というのも↑Mixinは対応)。エンコーディング問題というのはどこへ行っても頭を悩ませる種ですね。。。

IDCFクラウドのオブジェクトストレージをdjango-storagesから使ってみた。

最近はオブジェクトストレージをうまく使って、静的ファイルを配信するのが大きな潮流な模様。

静的ファイルのサイズが増え続けたり、ミニマムスタートでサービス立てたり、アプリケーションサーバー側をステートレスで必要に応じてスケーリングしたり...

オブジェクトストレージ殿は、そんな要求たちを一気にやっつけてくれるえらい奴だと、思い込んでおります。(全然実務の方ではご縁になることが、ややしばらくなさそうなんですけど...)

こないだ300円サーバーを作ってみたIDCFクラウドにもオブジェクトストレージのサービスがあって、50GBまでなら月額無料、転送もOUTトラフィック10GBまでは月額無料だというので、こりゃ試してみるのにはちょうどよさげだと思って、試してみることにしました。

www.idcf.jp

ちょうどDjangoさんを弄っていたところだったので、Djangodjango-storagesからS3のようにさくっと使えるだろうと思って始めたのですが... pypi.python.org

意外と情報がなくって微妙に苦戦したのでメモしておきます。S3互換のAPIが提供されているとはいえ、エンドポイントとかがS3とは違うわけなので、ライブラリにお任せする時にはちょっと設定をしないといけないのですね(あたりまえ)

IDCFクラウドの方は、コンパネからAPIユーザーを作って、バケットを作っておいてあげればOKです。 デフォルトだと非公開バケットができるので、バケットの詳細設定からパブリックしておく必要がありますね。

設定で必要になる情報は、APIユーザーを選択したときに最初に表示される画面(以下)に集約されています。 f:id:kacchan822:20161010224606p:plain

Djangoの方の設定は、基本的に公式ドキュメント通りで、以下のような感じになりました。 bucket_nameに作成したバケット名を入れましょう。idcfクラウドは基本的にサブドメイン形式な模様。

setting.py

INSTALLED_APPS = [
    ...

    'storages',

    ...
]

 ...

STATIC_URL = 'https://bucket_name.ds.jp-east.idcfcloud.com/'
STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
AWS_STORAGE_BUCKET_NAME = 'bucket_name'

 ...

これで、あとは、アクセスキーとシークレットキーを環境変数で渡してあげればOKだぜ!と思って

python manage.py collectstatic -n

ってやったら怒られました。つながんねーと的なことでした。Google大先生に尋ねたところ、 masato.github.io

こちらが大変参考になりました。~/.botoファイルに以下のような内容を書いてあげればよろしいよと。

~/.boto

[Credentials]
aws_access_key_id = xxxxxxxxxxxxxxxxxxxxxxxx
aws_secret_access_key = yyyyyyyyyyyyyyyyyyyyyyyyyy

[s3]
host = ds.jp-east.idcfcloud.com

これをつくってから、もう一度

python manage.py collectstatic -n

やったら、一生懸命あげる感じの雰囲気がでました。-n外してやったら確かにIDCFクラウドのオブジェクトストレージ上に保存されて、静的ファイルがそちらから配信されました。

ということで、とりあえずお試し完了です。


編集後記

アクセスキーとシークレットキーは環境変数経由で直接Djangoの設定ファイルへ渡せるっぽいけど、hostの方の設定はどうにかなるのだろうか。Djangoさんやら関係パッケージ周りの仕組みが未知数な部分がありすぎて謎だ。

IDCFクラウドに300円サーバーを作ってみた。

クラウドサーバーがあっちこっちにあって、どこがいいのだか全く謎ですが、ワンコイン(500円)という最小価格の安さでプッシュしている感の強いIDCFクラウドが目にとまりました。

とりあえず仮想マシン作成のテンプレートを眺めていたら、Ubuntu16.04がなくて悲しくなりましたが、公式以外の公開テンプレートを物色したところ、以下のような記事で紹介されているテンプレートを発見。

cloudyarouze.blogspot.jp

さくらクラウドやconohaクラウドだと仮想マシンの停止だけだと課金が続くので、こういう使い方には向かなくて、AWSとかの方になるだろうなと思っていたら、IDCFクラウドならディスクの方の課金は止まりませんが、マシン分の課金が止まるので、かなりお安くちょっとしたサーバーを建てられるということになるようです。

上のテンプレートを使うのもいいんですけど、せっかくなので、使ってみたかったSnappy Ubuntu Coreさんを使ってみることにしました。ここでIDCFクラウドのマイテンプレートなる機能が、力を発揮してくれます。

SnappyをIDCFクラウドで立ち上げるまで

1. マイテンプレートにSnappy Ubuntu CoreのOVAイメージをつくる

Snappyのページ(の下の方)から、OVAのイメージダウンロードURLを取得。 https://developer.ubuntu.com/en/snappy/start/#ova

今回、自分が使ったのはこのURL。 http://cloud-images.ubuntu.com/ubuntu-core/15.04/core/stable/current/core-stable-amd64-cloud.ova

マイページ→コンピューティング→テンプレートとたどっていくと、以下のようなテンプレートの管理ページが開きます。

f:id:kacchan822:20160915214825p:plain

ここで右上の緑色の「テンプレート作成」をクリックすると、以下のような画面がポップアップしてくるので、先ほど取得したURLをURLのところに入れて、その他の必須項目をいい感じ設定してあげて、フォームの最下部にある緑色の「テンプレートを作成」ボタンをクリックすれば作成が始まります。

f:id:kacchan822:20160915214839p:plain

ややしばらく待つと、

f:id:kacchan822:20160915215211p:plain

ステータスが「Download Complete」になってテンプレートが使える状態になります。

2. 作ったマイテンプレートから仮想マシンをつくる

コンピューティングの画面を開いていれば常に画面左上に入るっぽい水色の「仮想マシン作成」をクリックして、先ほど作ったマイテンプレートを指定してつくれば、OKです。

f:id:kacchan822:20160915215429p:plain

最小のプランのlight.S1で追加ディスクなし(ルートディスクの5GBのみ)にすれば、月額300円上限のお安いサーバーが仕上がります。

3. SSH接続のためのNAT設定をする

サーバーが立ち上がるまで少しだけ待ち時間があるので、この間にNATルーターの設定をしてあげます。IDCFクラウドの仮想サーバーたちは、デフォルトだと閉じたクラウドネットワークの中にいるようで、グローバルからつながりません。FWとポートフォワードの設定をしてあげる必要があります。

左側のメニューリストの「IPアドレス」をクリックするとグローバルIPの一覧が出るので、一つデフォルトで割り当てられるIPアドレスの名前をクリックして設定画面を開きます。

まず、FWで必要なポートを開けます。SSHの標準22を開けるのもありですが、雑な攻撃対策として、ポートを変えてみました。とりあえず2000とかにしてみます。 f:id:kacchan822:20160915220721p:plain

FWで開けたポートに対応するように、ポートフォワードの設定をします。
パブリックポートはFWで開けた、2000、プライベートポートは仮想マシンは標準ポートでSSHを待ち構えているので、22を指定します。仮想マシン側のsshの設定ファイルを調整せずにSSHのポート変更ができるという意味では、VPSとかを使う時より楽ちんです。 f:id:kacchan822:20160915220732p:plain

SSH接続できるか確認してみます。ユーザー名はubuntuで、ポート2000、仮想マシン作成時に指定した公開鍵とペアの秘密鍵を使って接続します。 f:id:kacchan822:20160915222203p:plain

うまくいけば、ウェルカムなメッセージが出るはずです。よきSnappyライフを。


という具合にして300円サーバーが出来上がりました。厳密には、マイテンプレートの保存料金が誤差の範囲ぐらいの額かかるようです。月額30円上限?課金の部分についてはよくわかりませんので、気になる方は実践する前にIDCFクラウドサポートに問い合わせてください。書いてある通りにやったら、300円以上かかったじゃないか!と言われても、私は責任を負いかねます....ご注意を。

国内のクラウドサービスとしては通信量に対する課金が無いところが多いイメージですが、IDCFクラウドは、デフォルトだと、月間3TBまでの通信が無料で、それ以上は従量課金ということです。3TBに行くのかな....。少し使ってみて様子を探ります。

PostfixAdmin的なものを作ってみた。

1台のメールサーバーで複数ドメイン運用したり、システムアカウントと連動せずにメールアカウント運用したいとかのときに、便利なPostfixAdmin( Postfix Admin - Web based administration interface)さん。

わたくしもお世話になっておりましたが、MySQLPostgreSQLと一緒にメールサーバーを動かしてあげないといけないのが面倒になってきた今日この頃...。LXDコンテナで流浪人のように移動しやすいコンテナとしておきたいわけです。もちろんMySQLでもPostgreSQLでもコンテナごと動かす分にはいんですけど、システムリソース的に...ということで...。

そんなオレオレ要件を満足させるものを作ってみました。 github.com

バーチャルメールユーザー管理画面

f:id:kacchan822:20160911135015p:plain

バーチャルメールユーザーの変更画面

f:id:kacchan822:20160911135033p:plain

バーチャルメールエイリアス管理画面

f:id:kacchan822:20160911135020p:plain

バーチャルメールエイリアスの変更画面

f:id:kacchan822:20160911135448p:plain

バーチャルメールドメイン管理画面

f:id:kacchan822:20160911135023p:plain

バーチャルメールドメインの変更画面

f:id:kacchan822:20160911135511p:plain

今回使ったもの

Pythonの軽量フレームワークのBottleをメインにして、UI部分と入力制御系をJavascriptで実装してみました。
本当は、PostfixAdmin的にユーザーログインによる認証機構もつけようとしたのですが、オレオレツールとしては、取り急ぎ必要ではないという英断により、未実装。これからお勉強がてら実装したいです。
Cork - Authentication for the Bottle web frameworkというのを使えばよさげかなと思っています。

今回、ちょっと積極的にcodeclimateさんのチェックを通しながらやったら、確かにコードが短くなったり煩雑だったところがすっきりとしました。(最初のコーディングが美しくな過ぎたというのはさておき....pythonやら、javascriptやら、jQueryやら、PostfixやらDovecotやらsqlite3やらいろんな勉強になったので、個人的には満足です。(これってよくあるダメなやつじゃないか...)

いうまでもなく、現状としてはデバックもかねて、SSHトンネル経由でbottleの簡易サーバー機能をそのまま使って動かしているレベルなので、実運用レベルにはありません。


ちなみにGoogle先生に「postfixadmin sqlite」尋ねてみたら、こんなのがあった。

github.com

2010年3月ごろからある模様。MySQLやらPostgreSQLやらを使ってやるまでの規模じゃないんだけど...なことはそりゃ考えるよな。


(2016.09.15 追記)

2016/09/12にPostfixAdmin3.0がついにリリースされたようで、なんと、add sqlite backend optionと言っているので、動作検証していないけどsqliteでも使えるようになったようです。

sourceforge.net