Month: August 2015

UPDATED 2017-03-22: Added SOCKS Proxy Configuration for Internet Explorer

外部からの接続(SSH、HTTPなど)を受け付けていないAzure 仮想ネットワーク(以下VNET)内のリソースにSOCKSプロキシを経由して外部からアクセスしましょうというお話。本記事ではAzure VNET内の外部からのアクセス許可していないVMへのSSHログインとHTTPサーバコンテンツへのブラウジングの2つの方法を紹介する。
SOCKS(RFC1928) とはさまざまなアプリケーションが間にファイアーウォールを挟んでいても安全に快適にやり取りができるようにすることを目的として作られたプロトコルのことで、SOCKSプロキシはSOCKSプロトコルを受け取りファイアウォール内外との接続を可能にするものである。エンドポイントやNetwork Security Group (NSG)によりネットーワーク分離設定されたAzure VNET内のリソースに対して一時的に本来直接アクセス許可しないネットワークからアクセスが必要な状況はあるかと思う。そのような時に毎回設定変更で必要なプロトコル、アクセス先に対して穴をあけるのは非常に面倒であり、またサイト間VPN、ポイント対サイトVPNとなるとさらに手間がかかる。お手軽に、もしくは定常的ではないが一時的に内部リソースにアクセスしたい場合にSOCKSプロキシ経由でのアクセスを検討してみてはいかがだろうか。以下はSOCKSプロキシ経由によるAzure VNET内のプライベートリソースへのアクセスイメージである。


Accessing-AzureVNET-via-SOCKSProxy

SOCKSプロキシの作成

まずはOpenSSHのダイナミックポートフォワード機能を使ってSOCKSプロキシを作成する。ダイナミックポートフォワードはSSHをSOCKSプロキシとして振舞うことを可能にする。SSHでアクセス先ホストと DynamicFoward(-D)でポートを指定することでlocalhostにSOCKSプロキシが立ち上がり指定のTCPポート(SOCKSプロキシサーバは基本的は1080だが、割り当て可能なポートであればどのポートでもOK)をlocalhost側からログイン先ホストのSSHサーバに転送することができるようになる。もちろん経路は暗号化される。現状のサポートプロトコルはSOCKS4とSOCKS5。
例えば上図でいうとJump Server(踏み台)にDynamicFoward(-D)1080でログインすると、Jump Serverにポート1080を転送するSOCKSプロキシが localhostに立ち上がり、そのlocalhost:1080に対してSOCKS4またはSOCKS5プロトコルで接続することでJump Serverを経由して通信を行うことができるようになる。
localhost ポート1080のJump Serverへのダイナミックフォワードは次のように-Dオプションで行う。

$ ssh -2 -D 1080 -l [Account] [Jump Server]

毎回-Dオプション指定が面倒な場合は、次のようにconfg(ssh_config)にDynamicForwardの記述することも可能。

~/.ssh/config

Host JumpServer
   User         [Account名]
   HostName/IP  [Jump Serverホスト/IPアドレス]
   Protocol 2
   ForwardAgent  yes
   DynamicForward 1080

上記OpenSSHの設定は、Linux/Macの場合は標準Terminalを使えばよいが、Windowsの場合はCygwin、XmingなどX端末エミュレータソフトをインストールしていただく必要がある。またX端末エミュレーターをインストールしなくともWindowsでは有名なSSHクライアントソフトPuttyがダイナミックポートフォワードに対応しているためPuttyを使ってSOCKSプロキシ作成することも可能。詳しくは「Dynamic Port Forwarding with SOCKS over SSH」が参考になるかと。

SOCKSプロキシを使ったSSH接続

次に上記で作成したSOCKSプロキシを経由してVNET内のサーバにSSH接続をする。 netcatでSOCKSプロキシを経由してlocalhostから目的のVNET内サーバ(ServerX)間にnetcatトンネルを作成してServerXにはそのnetcatトンネルを通じて接続する。

local$ ssh -2 -l [Account] -o 'ProxyCommand nc -x localhost:1080 %h %p' [ServerX]

netcat のプロキシ指定は-xオプションで行う。 ここでは事前に作成したSOCKSプロキシ(localhost:1080)を指定。 netcatトンネルの作成コマンドはProxyCommandに記述する。こちらも毎回長いオプション入力を避けるために config(ssh_config)設定すると便利である。

~/.ssh/config

Host ServerX
   User        [Account]
   Protocol 2
   ForwardAgent  yes
   ProxyCommand nc -x localhost:1080 -w1 %h %p

注意点として、netcatにはGNU本家版とそれ以外にいくつか派生があるが-x オプションの利用可能なnetcatである必要がある。オリジナルのnetcatやGNU netcatには-xオプションはない。ここで使用しているnetcatはIPv6に対応しているOpenBSD netcat。

もちろんVNET内のVMへのSSH接続の別解としてProxyCommandでJump ServerからServerXへnetcatトンネルを作成してlocalからServerXにログインすることも可能。

local$ ssh -2 -o 'ProxyCommand ssh [Jump Server] nc -w1 %h %p' [ServerX]

実はこの方法のほうがProxyCommand でプロキシ設定を行うため事前に別コンソールで何かを用意する必要がなく間違いなくSOCKSプロキシ経由での接続よりも楽。ではSOCKSプロキシ経由で接続する理由は何か? 理由は単純で、通常Jump Serverはセキュリティ設定上の理由でログインしてもほとんど何もできないようにするために機能を無効化していることが多く、よってnetcatが使えない(ncはおろかsshコマンド以外ほとんど何も使えない)環境だったりする。この場合、上記で説明したようにSOCKSプロキシ経由でのSSHログインが有効な手段となる。

SOCKSプロキシ経由でのブラウジング

ブラウザーにSOCKSプロキシ対応のプラグインを 入れることでブラウザーによるプライベートリソース(内部ネットワーク内のアプリ・ミドルウェア等のウェブUIを持った管理ツールなど)の閲覧も可能となる。有名なものにSwitchySharp(Google Chrome)やFoxyproxy(Firefox)などがある。以下簡単な設定スクリーンショットを乗せておく。共に「http://yoichika-*.cloudapp.net*」なURIパターンの時にのみSOCKSプロキシlocalhost:12345経由でアクセスする設定となっている。

Google Chrome – SwitchySharp


GoogleChrome-SwitcySharp

Firefox – Foxyproxy


Firefox-FoxyProxyStandard

Internet Explorer – Out-of-box feature
As answered in Stack Overflow, Internet Explorer does support SOCKS proxies.
Tools > Internet Options > Connections > LAN Settings > Proxy Server > Advanced


IE-SOCKS-PROXY

Enjoy Accessing private resources with SOCKS Proxy!

ARMとAzure Insights API

Azure上のさまざまなサービスのメトリック情報をAPI経由で取得したい。そういうことであればAzure Service Management APIを使えばいいじゃないかという声が聞こえてきそうなところだが実は既にこのやり方は時代遅れとなっていることをご存じだろうか?
2014年5月ごろ?に登場したAzureの新しい考え方にResource、ResourceGroup、Azure Resource Managerというものがある。簡単な説明すると、Azure上のPaaSインスタンス、仮想マシンなどすべての管理可能な資源をリソース(Resource)とよばれる単位に細分化し、それらをグループ化したものがResourceGroup、そして全てのリソースはAzure Resource Manager(以下ARM)というもので管理可能になっている。そしてこのARMで管理可能な世界のリソース群に紐づくメトリックデータはAzure Insights APIで取得可能となっている。本記事ではさまざまなリソースの中でもWeb Appsに絞って、Azure Insights REST API (Metric)を使ってそのメトリックを取得する方法について紹介する。

ARM Explorerでどのメトリックが取得可能なのか確認する

ARM Explorer (https://resources.azure.com/) をご存じだろうか? これはその名の通りAzure上の全てのリソース(ご利用のサブスクリプションに紐づく全てのリソース)のエクスプローラーであり、これを使うことでこのARM管理下の世界のすべてのリソースをエクスプローラービューで閲覧することができる。このARM Explorerで閲覧可能な各リソースの情報の中にmetricdefinitionsというものがあって、これにはそのリソースに対して指定可能なメトリックの種類やその定義情報などが格納されている。リソースのメトリック取得をする際は、まずはARM Explorerで目的のリソースのmetricdefinitionsから指定可能なメトリックの種類を把握してからAPIリクエストを組み立てていただければと思う。ARM Explorerを使って本記事で取得対象としているWeb Apps(ここではサイト名yoichikademoを対象)のmetricdefinitionsを閲覧しているのが以下のスクリーンショットになる。


ARMExplorer

Azure Insights REST APIメトリック取得インターフェース

Azure Insights APIには次のような(1)メトリック定義一覧の取得と(2)対象リソースのメトリック情報取得の2つのインターフェースがある。当然ながらメトリックの取得には(2)のインターフェースを使用する。

APIの共通部分は下記の通り。Azure Insights APIへの全ての要求はAzure Active Directoryを使用して認証する必要があり、この認証により得られたトークンを各APIリクエストのAuthorizationヘッダに指定する必要がある。トークン取得の方法にはPowerShellを使用した方法とAzure管理ポータルを使用して認証する2つの方法がある。詳しくは「Azure インサイト要求を認証する」を参照ください。

実際のメトリクス取得APIでは$filterパラメータの付与が必要となる。$filterには主にメトリックの種類(name.value)、時間レンジ(startTime – endTime)、インターバール(timeGrain)の3種類の条件を指定する。

CpuTimeとMemoryWorkingSetメトリック指定例 (実際は1行にまとめる)

$filter=
  (name.value eq ‘CpuTime’ or name.value eq ‘MemoryWorkingSet’)
  and startTime eq ‘2015-08-01T15:00:00Z’ and endTime eq ‘2015-08-02T15:00:00Z’
  and timeGrain eq duration’PT1M’

$filterパラメータには実際はURL Encodeかけた文字列を渡す。メトリックのインターバル(timeGrain)は1分単位なら”PT1M”、5分単位なら”PT5M”、1時間単位ならば”PT1H”、1日単位ならば”PT1D”などを指定する。

サンプルコード

Azure Insightsのメトリック取得APIを使ってWeb Appのメトリックを取得するサンプルコードをGithubにアップした。同様のことを考えている人にとって少しでも参考になれば幸いである。

https://github.com/yokawasa/azure-samples/tree/master/GetAppServiceMetrics

このサンプルではCpuTime、MemoryWorkingSet、AverageResponseTimeの3つのメトリック情報を1時間ごとのインターバルで2015-08-01~2015-08-30の期間分取得するようになっている。この部分はハードコーディングしているので必要に応じてソースコード(Program.cs)を適宜変更いただければと思う。また利用者ごとの情報は設定ファイルApp.configで指定する。以下簡単にApp.configの設定内容を解説する。

App.config

<appSettings>
    <add key="subscriptionId" value="[your subscription Id]" />
    <add key="resourceGroup" value="[your resource group name]" />
    <add key="siteName" value="[site Name]" />
    <add key="tenantId" value="[you tenant ID]" />
    <add key="applicationId" value="[your application id]" />
    <add key="redirectUri" value='[redirect url]' />    
</appSettings>

LINKS