最新 追記

雑記帳


2011-11-01 (Tue) [長年日記]

[AWS] Amazon VPCで複数拠点接続(2)

前回、複数拠点でVPN接続ができたので、拠点間通信のテストをしてみた。

正しく設定ができていれば、拠点間の通信は問題なくできることが確認できたのだが、問題は、それぞれの拠点間で通信をさせたくない、というケース。

基本的には、ルータ側で制限をするということになるのだが、そのような設定がVPCでできるのかどうか調べてみた。具体的には、VPCでは、セキュリティグループだけでなく、Network ACLという、サブネット単位でネットワークのアクセスポリシーを変更できる機能がある。これを使って制限ができるかどうか調べてみた。

結論からいうと、拠点間通信のポリシーはVPCではできないようだ。

Network ACLは、あくまでVPCのサブネットの出入りに関するポリシーであって、拠点間の通信には影響がない。

例えば、Network ACLで、VPN接続をしているサブネット、例えば192.168.1.0/24からVPCへのInboundをすべて拒否してみる。すると当然、192.168.1.0/24からは、VPC内のEC2などには通信ができなくなる。しかし、他の拠点、たとえば192.168.2.0/24に対しての通信は、拠点間通信では、Network ACLを経由しないため、特に影響がない。

Network ACLの設定は、InboundであればSourceの設定しかないし、OutboundであればDestinationの設定しかない。いずれにしても、もう片一方は、Assosiationされているサブネットとなる。

当然といえば当然の事なのだが、テストすることで確認できたのでよしとする。


2011-11-04 (Fri) [長年日記]

[Linux] Debianでnagiosによる監視

普段はCentOSでやっていることをDebianでやってみた。

インストールが必要なパッケージは、以下のとおり。

# aptitude install nagios-nrpe-server nagios-nrpe-plugin nagios-plugins

nrpeの設定ファイルは、/etc/nagios/nrpe.cfgなので、allowd_hostsで監視サーバを許可する設定をする。また、サーバ側から引数を渡せるように、dont_blame_nrpeを0から1に変更する。

インストールすると、自動的に起動し、自動起動するように設定されるようだ。設定ファイルを更新した後に再起動しておく。起動スクリプトは、/etc/init.d/nagios-nrpe-server

これで、nagiosによる監視ができるようなる。

[Linux] nagiosのcheck_httpでcooikeを付与する

nagiosのcheck_httpを使って監視をする際に、特定のCookieを渡す必要ができたので、調べてみた。

ドキュメントによると、-k, --headerオプションで、任意のヘッダが渡せるので、こちらにCookieを書けばよいことが分かった。

ということで、コマンドを直接実行するなら、以下のような感じになる。

$ ./check_http -H example.com -I 192.168.10.20 -u '/path/to/example.php' -k 'Cookie: ID=8jg423blfv92ruu8kmbq21eb17'

ここでは固定の値になってしまうので、取得されたCookieを自動的に次回使う、というのは無理みたい。

[PostgreSQL] 新しいバージョンのPostgreSQLをrpmでインストールする

ContOSなどの、rpmを使っているディストリビューションで提供されているPostgreSQLのバージョンよりも、新しいバージョンのPostgreSQLを使いたい、という場合がある。その場合は、PostgreSQL RPM Repository (with Yum)で提供されているものが使える。

Repository Packagesの一覧から、対応するディストリビューションのyumリポジトリのsourceをインストールできるrpmを取得して、それをインストールする。すると、/etc/yum.repos.d/に、対象となるPostgreSQL関連のパッケージが含まれるリポジトリの設定がインストールされるので、その状態からyumを使ってインストールすることができる。ちなみに、このリポジトリで提供されているパッケージは、パッケージの一覧に記載されている。

例えば、PostgreSQL 9.0のリポジトリを追加して、yumでリポジトリの一覧を見ると、pgdg90が追加されているのが分かる。

# yum repolist
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: centosv4.centos.org
 * epel: mirrors.coreix.net
 * extras: centoso4-msync-dvd.centos.org
 * remi: rpms.famillecollet.com
 * rpmforge: ftp-stud.fht-esslingen.de
 * updates: centoso4-msync-dvd.centos.org
repo id                    repo name                                                          status
base                       CentOS-6 - Base                                                    6019
epel                       Extra Packages for Enterprise Linux 6 - x86_64                     6546
extras                     CentOS-6 - Extras                                                     1
pgdg90                     PostgreSQL 9.0 6 - x86_64                                           104
remi                       Les RPM de remi pour Enterprise Linux 6 - x86_64                    392
rpmforge                   RHEL 6 - RPMforge.net - dag                                        4089
updates                    CentOS-6 - Updates                                                 1042
repolist: 18193

あとは、通常と同じようにyumでパッケージを探して、必要なものをインストールすれば良い。


2011-11-11 (Fri) [長年日記]

[AWS] IAMでアクセスキーを変更できるアカウントを作成する

SimpleDBやS3などは、AWSの管理者ではなく、実際の利用者にアクセスキーを渡して使ってもらうことが多い。

以前に書いたように、アクセスキーは90日ごとにに変更することが推奨されている。パスワードを定期的に変更するのと似たようなことなので、アカウントを使用している人が変更できたほうが良い。

ということで、アクセスキーを変更できるポリシーを作ってみた。

{
  "Statement": [
    {
      "Action": [
        "iam:CreateAccessKey",
        "iam:DeleteAccessKey",
        "iam:ListAccessKeys",
        "iam:UpdateAccessKey"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:iam::123456789012:user/user_name"
      ]
    }
  ]
}

アクセスキーに関するアクションは、作成(CreateAccessKey)、削除(DeleteAccessKey)、一覧(ListAccessKeys)、更新(UpdateAccessKey)となる。更新は、アクセスキーの置き換えではなく、ActiveとInactiveの状態を変更するためのアクション。これだけの権限があればアクセスキーの変更ができる。

アクセスキーの変更ができる対象として、user_nameという名前のIAMユーザを指定している。これを指定しない場合は、他のユーザのアクセスキーも変更可能になる。

AWSの各プロダクトごとのIAMのポリシー関連は、IAMのドキュメントのIntegrating with Other AWS Productsからすぐに参照できる。

[AWS] IAMで、S3のバケット内の特定のオブジェクト以下のみ許可する

※ 2013-04-18更新 誤りがあったので訂正。Policyのみの設定で問題なく、Permissionの設定は不要だった。

S3に、いろいろなユーザがアクセスする際に、あるユーザが、あるバケットの特定のオブジェクト以下のみアクセスを許可したい場合の権限を作成してみた。条件としては、以下のとおり。

  • バケット名: bucket_name
  • 許可したいオブジェクト: /path/to/dir
  • バケット名の一覧は見える
  • 対象のバケット以外は、中が見えない
  • 対象のディレクトリ以外は、一覧は見える
  • 対象のディレクトリ内は、自由に読み書きできる

で、なかなかうまく行かなかったので試行錯誤した結果できたのが、以下のポリシー。

{
    "Statement": [
        {
            "Action": "s3:ListAllMyBuckets",
            "Effect": "Allow",
            "Resource": "*"
        },
        {
            "Action": "s3:ListBuckets",
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::backet_name"
        },
        {
            "Action": [
                "s3:*"
             ],
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::backet_name/path/to/dir/*"
        }
    ]
}

s3:ListAllMyBucketsで、すべてのバケットのリストが見られるように許可。s3:ListBucketsで、対象となるバケットのみ見られるように許可。 最後の部分は、特定のオブジェクトのみ許可、となっている。

これで、期待通り書き込みができるようになる。


2011-11-14 (Mon) [長年日記]

[AWS] IAMアカウントでX.509証明書が使えるようにする

IAMアカウントが必要なときは、大抵の場合アクセスキーIDで事足りることが多い。しかし、EC2関連のCLIを実行するときにX.509証明書が必要になってくる。

アクセスキーIDは自動的に作成され、AWS Management Consoleで管理できるのだが、X.509証明書は作成されない。IAMのドキュメントによると、次のようにある。

IAM doesn't have an API action to create signing certificates, so you must use a third-party tool such as OpenSSL to create the certificate first. We recommend you create an RSA key that is either 1024-bit or 2048-bit in length. The certificate can be self-signed, and the key and certificate must be in PEM format. For more information about OpenSSL, go to http://www.openssl.org/.

ということで、OpenSSLを使って作成し、AWSに登録する必要がある。

秘密鍵を作成する

RSAの秘密鍵を作成する。鍵長は、1024もしくは2048ビット。

$ openssl genrsa -out iam.key 2048

CSRを作成する

秘密鍵からCSR (Certificate Signing Request, 証明書署名要求)を作成する。

$ openssl req -new -key iam.key -out iam.csr

ここで色々と聞かれるが、任意の内容で問題ない。

証明書を作成する

作成した秘密鍵とCSRから、証明書を作成する。

$ openssl x509 -req -in iam.csr -signkey iam.key -out iam.pem

証明書を登録する

作成した証明書を、AWSに登録をする。

AWS Management ConsoleのIAMからユーザを選択し、Security Credentialsを選択し、証明書をアップロードするための「Manage Signing Certificates」を押す。

IAM User

「Upload Signing Certificate」を押す。

Manage Signing Certificates

証明書を貼り付けて、「OK」を押す。

Upload Signing Certificate

これで登録できた。あとは、CLIで証明書が必要なコマンドを実行する際に、登録した証明書と鍵を使って実行すれば良い。

ちなみに、この時登録される証明書は、AWS内ではユニークでなければならないようだ。つまり、使い回しができない。テストするために使いまわそうとしたら、登録時にエラーがでてしまった。仕組みを考えると当然なのだが、実際にやってみるまで気が付かなかった。


2011-11-17 (Thu) [長年日記]

postfixadminでメールボックスに配送しつつ転送する設定

postfixadminを使っていて、メールボックスあてのメールを、メールボックスに配送しつつ、別のメールに転送したかったのだが、転送設定に追加しようとしても、出来なかった。

実現する方法はあるはず…と思って調べてみたら、あった。config.inc.phpに、Alias Controlという設定で制御できるらしい。

// Alias Control
// Postfix Admin inserts an alias in the alias table for every mailbox it creates.
// The reason for this is that when you want catch-all and normal mailboxes
// to work you need to have the mailbox replicated in the alias table.
// If you want to take control of these aliases as well set this to 'YES'.

// Alias control for superadmins
$CONF['alias_control'] = 'NO';

alias_controlをYESにすると、メールアドレスの設定項目に、"転送"が現れるので、ここから設定できる。

postfixadmin


2011-11-18 (Fri) [長年日記]

[AWS] ELBでHTTPリスナーだとWebSocketは使えない

ELBを使っていて、WebSocketを使おうとしたときに、最初のハンドシェイクが上手くいかないという問題に遭遇した。

テストするために、node.jpのドキュメントから、http.ClientReqestにあるサンプルを使ってみた。ここのEvent: 'Upgrade'のところにあるサンプルコードを若干改造して下記のようなコードを用意した。

var http = require('http');
var net = require('net');

// Create an HTTP server
var srv = http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('okay');
});
srv.on('upgrade', function(req, socket, upgradeHead) {
  socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
               'Upgrade: WebSocket\r\n' +
               'Connection: Upgrade\r\n' +
               '\r\n\r\n');

  socket.ondata = function(data, start, end) {
    socket.write(data.toString('utf8', start, end), 'utf8'); // echo back
  };
});

// now that server is running
srv.listen(3001, '0.0.0.0', function() {});

これを、test.jsとして、node.jsを起動すると、ポート80で待ち受ける。

これに対して、例えば、次のようなリクエストを送る。

GET http://websocket-xxxxxxxxxx.ap-northeast-1.elb.amazonaws.com/ HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: websocket-xxxxxxxxxx.ap-northeast-1.elb.amazonaws.com

WebSocket的には、次のようなリクエストを返してくるはず。

HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade

しかし、実際には、単純な200 OKが返ってきてしまう。

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 4
Connection: keep-alive

okay

ec2に直接リクエストをすれば、期待した通りの結果が帰ってくるのだが、ELBを介すると、正しく動作しない。EC2上でtcpdumpを実行して確認してみたところ、下記のように、ELBがリクエストヘッダから、UpgradeやConnectionを削除してしまっていることが分かった。

GET / HTTP/1.1
host:websocket-xxxxxxxxxx.ap-northeast-1.elb.amazonaws.com
X-Forwarded-For: xxx.xxx.xxx.xxx
X-Forwarded-Port: 80
X-Forwarded-Proto: http
Connection: keep-alive

リスナーがHTTPではなければ問題ないだろうと思ったので、リスナーをHTTPからTCPに変更してみたところ、ヘッダが削除されることはなく、期待したとおりのレスポンスが返ってきた。

ということで、WebSocketを使うサービスをELBで負荷分散する場合は、リスナーをTCPにする必要がある。

追記: 問題の原因は、WebSocketはHTTPに似ているがHTTPではないため、ということのようだ。WebSocketというものをよく理解していなかった。

また、ELBは、httpリスナーの場合だと60秒でセッションが切れるので、WebSocketを使うときにはやはりTCPで接続する必要があるようだ。


2011-11-22 (Tue) [長年日記]

[AWS] EBSブートのインスタンスのリージョン変更手順

ESBブートのインスタンスのリージョンを変更してみた。

ツールのインストールと設定

下記のツールを移行対象となるインスタンスにインストールする(Amazon Linux AMIの場合は元々入っているか、yumで入れられる)。

  • aws-apitools-ec2
  • aws-amitools-ec2
  • ec2-utils

ちなみに、AMI Toolsは、Rubyとrsyncが入ってないと動かない。

イメージファイルを作成

ec2-bundle-volコマンドを使って、イメージファイルを作成する。特に指定しない場合、/tmpに作成されるので、ディスクに十分な空きがあるか注意しておく。

# ec2-bundle-vol -k ~/.ec2/ec2.key -c ~/.ec2/ec2.crt -u YOUR_ACCOUNT_NUMBER --region ap-southeast-1 -r i386

作成したイメージをマイグレートする

ec2-migrate-manifestコマンドを使って、イメージファイルを別リージョンに転送する前に、別リージョンで動作するようにマイグレートを行う。--regionには、移行先のregionを指定する。

# ec2-migrate-manifest -k ~/.ec2/ec2.key -c ~/.ec2/ec2.crt --manifest /tmp/image.manifest.xml --region ap-northeast-1

S3にアップロードする

ec2-upload-bundleコマンドを使って、マイグレートしたイメージを、移行先リージョンのS3にアップロードする。対象がS3なので、アクセスキーIDを使う。

# ec2-upload-bundle -a YOUR_ACCESS_ID -s YOUR_SECURET_ACCESS_KEY -b migrate-bucket -d /tmp -m image.manifest.xml

マイグレートしたイメージからAMIを作成する

S3にあるイメージからAMIを作成する。

# ec2-register migrate-bucket/image.manifest.xml -K ~/.ec2/ec2.key -C ~/.ec2/ec2.crt --region ap-northeast-1

作成したAMIからインスタンスを起動する

# ec2-run-instances -K ~/.ec2/ec2.key -C ~/.ec2/ec2.crt ami-b29025b3 --region ap-northeast-1

ここで起動できたインスタンスは、EBSブートのインスタンスではない。ここからEBSボリュームを作成する。

インスタンスに接続する

起動したインスタンスにsshする。この場合、もともとのサーバと同じディスクなので、既存のユーザでログインすることができる。

起動したインスタンスのイメージファイルを作成する

EBSに書き込むため、ec2-bundle-volコマンドで、バンドルボリュームを作成し、それをec2-unbundleコマンドでイメージに変換する。

# cd /tmp
# ec2-bundle-vol -d /tmp -k ~/.ec2/ec2.key -c ~/.ec2/ec2.crt -u YOUR_ACCOUNT_NUMBER
# ec2-unbundle -k ~/.ec2/ec2.key -m /tmp/image.manifest.xml -s /tmp/ -d /tmp/

EBSボリュームを用意する

EBSインスタンス用のEBSボリュームを作成し、アタッチする。

# ec2-create-volume --size 10 --availability-zone ap-northeast-1a --region ap-southeast-1
# ec2-attach-volume vol-48f73422 --instance i-32dda733 -d /dev/sdf1 --region ap-northeast-1

EBSボリュームにイメージを書き込む

# dd if=/tmp/image of=/dev/sdf1

データサイズに応じて、それなりに時間がかかるので注意。

EBSによるAMIの作成

まず、スナップショットを作成する。

# ec2-create-snapshot vol-48f73422 --region ap-northeast-1

すこし時間がかかるので、作成されたのを待ってAMIを登録する

# ec2-register --snapshot snap-2d2ccf46 --description="migrated image" --architecture i386 --root-device-name /dev/sda1 --name migrated image --region ap-northeast-1

できたAMIから起動すると、EBS Rootで起動できる。


2011-11-29 (Tue) [長年日記]

[AWS] AWS Multi-Factor Authenticationを使う

AWS Multi-Factor Authentication(AWS多要素認証/AWS MFA)とは、ユーザがAWSにアクセスをする際に、通常のAWSアカウントとパスワードに加えて、利用者が物理的に所有している認証デバイスから有効な6桁の数字(ワンタイムパスワード)を使って認証する機能のこと。

AWS MFAでは、時間ベースのワンタイムパスワードを生成できるデバイスが使える。これは、RFC 4226がベースになっていて、現在ドラフトとなっているTime-based One-time Password Algorithmが元にとなっている。

AWSのページでは、物理デバイスをgemaltoから購入できるとしているが、これと同等の機能を持つGoogle Authenticatorという、iOSとAndroidで動作するアプリがあるので、それを使うことですぐにAWS MFAを始めることができる。

ということで、早速やってみることにする。

が、その前に注意点。AWS MFAをAWSアカウントで一旦有効にしてしまうと、自分の手では無効にできなくなる。無効にするには、問い合わせフォームからAWSに連絡をしなければならない。IAMアカウントであれば、管理者が無効にすることができるので、ちょっとお試しでやるのであれば、IAMアカウントで試すのが吉。

後日追記: 後に気がついたのだが、AWSアカウントで、MFAデバイスを無効化するには「セキュリティ証明書」のページで可能のようだ。デバイスを無効にして、MFAそのものも同時に無効にできる。

Google Authenticatorインストール

iOS版もしくはAndroid版を事前にインストールしておく。

IAMアカウントでMFAを有効にする

対象となるIAMアカウントの、Security Credentialsタブから、Manage MFA Deviceボタンを押す。

Manage MFA Deviceボタン

すると、MFAデバイスの種類を選択するダイアログが表示される。今回は、virtual MFA deviceを選択して次に進む。

Select virtual MFA device

MFAアプリのインストールについての説明が表示されるので次に進む。

MFA application

QRコードが表示される。

QRコード

ここでGoogle Authenticatorを起動して右下の+ボタンを押すと、トークンを追加する画面になる。

トークンを追加

下の方にある、バーコードをスキャンボタンを押すとカメラが起動されるので、表示されているQRコードをスキャンする。

スキャンに成功すると、ワンタイムパスワードが表示されるようになる。

ワンタイムパスワード

QRコードが表示されている下に、Authentication Code 1と2を入力できる項目があるので、Google Authenticatorに、今表示されている数字を入力する。左上にある円グラフのようなタイマーが一巡すると数字が新しくなるので、さっき入力した次に表示された数字を入力する。 問題なければ、これでMFAが使えるようになった。

ログイン

このアカウントで実際にログインしてみる。すでにパスワードが有効なIAMである必要があるので要確認。

IAMのDashboardに記載されているログインURLにアクセスする。

Sign In

ユーザ名とパスワードを入力するフォームが表示されるので入力する。その次に、Authentication Codeを入力するフォームが現れるので、現在Google Authenticatorに表示されている数字を入力する。問題なければ、ログインできる。

Authentication Codeを入力

これで、特定のIAMアカウントで、MFAを使うように設定できた。ログインするには、必ずデバイスに表示されるワンタイムパスワードを入力しなければならないので、仮にパスワードがもれたとしてもログインすることは難しくなる。

今回はテストのため、IAMアカウントで試してみたが、AWSアカウントでも同様に設定することができる。


2011-11-30 (Wed) [長年日記]

[Linux] ログインに失敗したアカウントをロックする

セキュリティの要件として、ログインに複数回失敗したらアカウントをロックしたい、ということがあったので、設定してみた。対象となるディストリビューションは、CentOS 6.0。

実現するには、pamのpam_tally2.soモジュールを使う。 /etc/pam.d/password-authのauthタイプに、下記二行目のように追記する。

auth        required      pam_env.so
auth        required      pam_tally2.so deny=3
auth        sufficient    pam_unix.so try_first_pass nullok
auth        required      pam_deny.so

オプションのdeny=3は、3回失敗したらアカウントがロックされるという設定になる。一度ロックされると、管理者がロックを解除しない限りロックされたままになる。

ロック状態を自動的に解除するには、unlock_timeオプションを使えばよい。指定した時間が経過したらロックが解除される。その他のオプションについては、man pam_tally2を参照のこと。

ログインに失敗した回数は、/var/log/tallylogに記録される。これはバイナリなので、状態を確認するには、pam_tally2コマンドを使う。

# pam_tally2 -u pamtest
Login           Failures Latest failure     From
pamtest             5    11/30/11 19:43:45  xxx.xxx.xxx.xxx

回数をリセットするには、--resetオプションを使う。

# pam_tally2 -u pamtest --reset

この時、何故かリセットされる前の失敗回数が出力されるので注意。