designetwork

ネットワークを軸としたIT技術メモ

Express + Node.jsでDNS名前解決の状況を確認する

サーバ間のAPI連携などの際のDNS名前解決確認ツールをExpress + Node.jsで作成した。サーバ上でNode.jsで名前解決をするため、実際のアプリケーションと同じ環境での確認ができる。

確認できること

DNSの名前解決 (Webアプリケーション自身から)

以下の通り、FQDNに対するAレコード、PTRレコードを確認できる。

f:id:daichi703n:20170311201728p:plain

公開プログラム

Herokuにてプログラムを公開している。(フリープランなので立ち上がり遅い場合あり)

DNS Checker - Heroku

できないこと・修正したい点

こちらと同様

designetwork.hatenablog.com

ソースコード

Express + Node.jsのソースコードはこちらで公開している。ご自由にお持ちください。

仕組みとしては、jadeのformでFQDNを入力し、クエリとしてNode.jsで読み込む。与えられたFQDN(クエリ)に対してnpm dnsモジュールでアクセスして名前解決情報を取得する。なお、localhostについてはDNSでの名前解決ができないため、npm pingモジュールで同様情報を取得する。

www.npmjs.com

www.npmjs.com

まとめ - Express + Node.jsでDNS名前解決の状況を確認する

Express + Node.js dns, pingモジュールにより、アプリケーション自身がFQDNの名前解決して結果を表示するプログラムを作成した。Webアプリケーション, API基盤の動作確認等の用途に使用できる。

ASAでDMZを構築するときのセキュリティレベル設定

f:id:daichi703n:20170311162820j:plain

Cisco ASA5505で自宅ラボにDMZを構築している。単純なinside-outside設定の場合はセキュリティレベルをinside:100, outside:0とし、必要な外からの通信をFWとNATで許可すればよい。

しかし、DMZを含めるとセキュリティレベルだけでは制御しきれなくなる。一般的にDMZ:50としてセキュリティレベルを設定する。これにより、以下のようなアクセス制御になる。

o inside -> outside
o inside -> dmz
x dmz -> inside
o dmz -> outside
x outside -> inside
x outside -> dmz

ACLを適用すると上書きされる

上記のxの通信についても、要件に応じて通信可能とする必要がある。例えばインターネット公開サーバなど。outsideからの通信はACLとNATで実現できる。しかし、問題となるのはdmzからinsideへの通信。

基本的には、セキュリティレベル低->高(dmz->inside)の通信はACLで穴あけしていくことになるが、そのときにdmz->outsideへの通信も考慮が必要となる。セキュリティレベルでの動作を期待すると、以下のように、insideへの必要通信のみを設定しがちだ。

access-list dmz extended permit ip <dmz> <inside>
access-group dmz_in in interface dmz

しかし、このACLを適用してしまうと、dmzからoutside(インターネット)への通信ができなくなってしまう。つまり、ACLでセキュリティレベルの設定が上書きされてしまう。

そのため、以下のようにinsideの特定ホスト宛は許可、他は拒否、その上でany(outside)宛は許可とする必要がある。(ACLの書き方はOSバージョン等による)

access-list dmz extended permit <protocol> <dmz> <inside_host>
access-list dmz extended deny ip <dmz> <inside>
access-list dmz extended permit ip <dmz> any
access-group dmz_in in interface dmz

設計メモ

設計ポイント、エラーの対処などはこちらを参照

まとめ - ASAでDMZを構築するときのセキュリティレベル設定

自宅ラボASA5505でDMZを構築するときは、セキュリティレベルでの制御はしきれず、DMZからの通信はすべてACLで制御する必要がある。

自宅ラボASAでDMZからinsideに通信できない問題に対応する

自宅ラボのASA5505でDMZを構築していたら、DMZからinsideへの通信ができない事象が発生したので対応メモ。

前提構成

  • Cisco ASA5505(基本ライセンス・BASE License, Ver.9.2(3))
  • Cisco Catalyst2960
  • VMware ESXi

ASA5505はセキュリティライセンスがないとVLAN trunkができないためCatalystaccessで各々接続して束ねている。

DMZからinsideへの通信ができない

適切なACLをインタフェースに適用して疎通確認をしたが、DMZからinsideへの通信ができない。

インタフェースの設定・セキュリティレベル等はこちらの通り。insideのVLAN名はmanagement。

ASA5505# sh run int

interface Vlan1
 nameif management
 security-level 100
 ip address 192.168.1.x 255.255.255.0 
!
interface Vlan50
 no forward interface Vlan1
 nameif dmz
 security-level 50
 ip address 192.168.50.xx 255.255.255.0 
!
interface Vlan99
 description internet
 nameif outside
 security-level 0
 pppoe client vpdn group nifty
 ip address pppoe setroute 

no forward interface Vlan1についてはこちら

NATとACLの設定はこちら。サーバ数が少なく、随時試験中のためACLは広めに空けている。NATのルールは見直しの余地あり。

ASA5505# sh run nat
nat (outside,management) source static any any destination static interface Web-01 service OpenWeb Web
nat (management,outside) source dynamic Internet-PAT interface
nat (dmz,management) source static any any unidirectional  //Does not work because of no forward
nat (dmz,outside) source dynamic Internet-PAT interface

ASA5505# sh run access-list 
access-list Web extended permit tcp any any eq www 
access-list dmz extended permit ip any any 

ASA5505# sh run access-group 
access-group Web in interface outside
access-group dmz in interface dmz

ASA内部のパケットトレーサーでキャプチャすると以下の通り。no-forward-ruleによってパケットがドロップされている。

ASA5505# packet-tracer input dmz icmp 192.168.50.x 0 0 192.168.1.x 

Phase: 1
Type: ROUTE-LOOKUP
Subtype: Resolve Egress Interface
Result: ALLOW
Config:
Additional Information:
in   192.168.1.0     255.255.255.0   management

Phase: 2
Type: ACCESS-LIST
Subtype: no-forward-rule
Result: DROP
Config:
Additional Information:

Result:
input-interface: dmz
input-status: up
input-line-status: up
output-interface: management
output-status: up
output-line-status: up
Action: drop
Drop-reason: (acl-drop) Flow is denied by configured rule

そんなACLは設定していないが、パケットトレーサーの出力の通り、インタフェース設定のno forwardによって拒否されている。

interface Vlan50
 no forward interface Vlan1

Cisco ASA5505のVLAN構成

Cisco ASA 5505 適応型セキュリティ アプライアンス用スイッチ ポートおよ び VLAN インターフェイスの設定 - Cisco Systems

設定ガイドの中では以下のようなVLAN構成が記載されている。

f:id:daichi703n:20170222004855j:plain

図中のホームVLANno forward interface Vlanビジネスが設定されていることになる。

これを見直して、インターネット接続のoutsideからmanagement(inside)へをno forwardとするのが妥当ではないかと考える。

f:id:daichi703n:20170222010649p:plain

outsideインタフェースにno forwardを設定する

DMZからinsideへの通信はR-Proxyなど各種通信で必要となる。そのため、DMZのno forwardを解除し、その代わりにoutsideにno forwardを設定する。

単純にno forwardの設定を追加しようとするとエラーになる。

ASA5505(config-if)# interface Vlan99
ASA5505(config-if)# no forward interface vlan 1
ERROR: Interface Vlan1 is already used in another no forward command
ASA5505(config-if)# no forward interface vlan 50
ERROR: Interface Vlan50 is already used in another no forward command

試しに使用していないVLAN宛のno forward設定をしたら、正常に設定できた。実際の通信も問題なく、各インタフェース間ですべてルーティングできる。ただし、dmzからinsideへの通信にはACLが必要。ACL適用時にはinternet宛もpermitが必要。

outsideからinside(Vlan 1)への通信を捨てるつもりだったが、移行のしやすさを考慮して継続通信できるに越したことはない。

ASA5505(config-if)# no forward interface Vlan 10
ASA5505(config-if)# exit
ASA5505(config)# interface Vlan50
ASA5505(config-if)# forward interface Vlan 1

最終的なインタフェースの設定は以下の通り。

ASA5505# sh run int vlan 1 
!
interface Vlan1
 nameif management
 security-level 100
 ip address 192.168.1.5 255.255.255.0 
ASA5505# sh run int vlan 50
!
interface Vlan50
 nameif dmz
 security-level 50
 ip address 192.168.50.1 255.255.255.0 
ASA5505# sh run int vlan 99
!
interface Vlan99
 description internet
 no forward interface Vlan10
 nameif outside
 security-level 0
 pppoe client vpdn group nifty
 ip address pppoe setroute 

まとめ - 自宅ASA(BASE License)でDMZからinsideに通信できない

自宅ラボで使用しているASA5505で、DMZからinsideへの通信ができない事象が発生した。問題はASA5505 基本ライセンスでは設定が必要となるno forward interfaceの影響だった。最終的に、no forward interfaceをoutsideに設定し、かつ、指定VLANを未使用のものにすることで、(ACLポリシーで制御した上で)全インタフェース間で通信が可能となった。

Ansibleの動作が遅いときに確認・修正する項目

f:id:daichi703n:20170307232809p:plain

Ansibleを使い始めたときに、設定量が多くなってくると動作が遅くなった。原因切り分けして解消したので確認ポイントをメモする。(CentOS7.3 ansible 2.2.1.0)

結果としてDNSタイムアウト待ちが発生していた。なお、FQDN以外のlocalhostでのAレコード(正引き)、IPアドレスでの指定でもPTRレコード(逆引き)の問い合わせをする。

tcpdumpによる切り分け

ansible-playbookを実行すると毎回決まった時間がかかっているように見える。固定的に遅い場合は大抵何かのタイムアウト待ちで、DNSが多い。tcpdumpで動作を確認する。

まず、インタフェース情報を確認する。

$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    ...
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
    ...

確認したインタフェースでDNS(53)のパケットのみをキャプチャする。-nnオプションを付けることで、Well-Knownポート番号の文字列変換を無効化する。ポート53の場合はdomainと表示されるが逆に分かりづらい。(キャプチャは正常時のシーケンス)

$ sudo tcpdump -i ens192 -nn port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens192, link-type EN10MB (Ethernet), capture size 65535 bytes
07:30:16.609964 IP 192.168.1.75.40927 > 192.168.1.77.53: 19540+ A? h-cent-mng01.designet.local. (45)
07:30:16.610591 IP 192.168.1.77.53 > 192.168.1.75.40927: 19540* 1/0/0 A 192.168.1.75 (61)
07:30:16.610660 IP 192.168.1.75.40927 > 192.168.1.77.53: 1216+ AAAA? h-cent-mng01.designet.local. (45)
07:30:16.611196 IP 192.168.1.77.53 > 192.168.1.75.40927: 1216* 0/1/0 (106)
07:30:16.822439 IP 192.168.1.75.43660 > 192.168.1.77.53: 18414+ PTR? 75.1.168.192.in-addr.arpa. (43)
07:30:16.822750 IP 192.168.1.77.53 > 192.168.1.75.43660: 18414* 1/0/0 PTR h-cent-mng01.designet.local. (84)

このようにDNSでA, AAAA, PTRの各レコードを問い合わせていることが分かる。

Ansible hostsファイルでの指定による差異

DNSの問題と聞くと、FQDN指定の場合を想定するかと思う。しかし、Ansibleではlocalhost及びIPアドレスでの対象サーバ指定の場合でも各レコードの名前解決を試みる。そのため、「まだDNS登録していないから暫定でIPアドレス指定で…」としている場合に、動作遅延の問題が顕在化する。

Ansible動作遅延の解消

解消方法は単純で、以下のいずれかの対応をすれば良い。

  • A, AAAA, PTRレコードをDNSサーバに登録する
  • DNSサーバでNon-Exist(NXDomain)を返すようにする(タイムアウト待ち防止)

まとめ - Ansibleの動作が遅いときに確認・修正する項目

Ansibleの動作が遅いときは、DNSタイムアウトを疑うといい。tcpdumpで原因調査し、DNSの問題だと分かったら、DNSサーバに必要なレコードを登録するか、DNSサーバでNXDomainを返すようにすることで問題が解消する。

他にもyumのProxyなどの要因はあるが、tcpdumpで異常通信を確認する今回のプロセスは有効に機能する。

Outlookの振り分けルールでAND/OR条件を組み合わせる

f:id:daichi703n:20170305153711p:plain

Outlookで振り分けルール設定をする際に、通常の設定だと、AND/ORの組合せがうまくできず、かゆいところに手が届かない。特にOR条件を使いたいときにおすすめの設定を紹介する。

Microsoftコミュニティ

Microsoftコミュニティで同様のディスカッションがあるが、最終的に検索の話になっており、期待する回答はない。

answers.microsoft.com

メール振り分けにヘッダ情報を使用する

通常の振り分けルールでは、項目間の関係はかつ(AND)になっている。そのため、通常ルールでは差出人がX、または、件名に"Y"を含むという設定はできない。

そこで、振り分けルールのうちヘッダ情報を使用する。

OutlookでのAND/OR組合せ振り分け

OutlookでOR条件の振り分けルールを作成する方法を示す。画面はWeb版Outlookだが、クライアント版でも同様箇所で設定ができる。

f:id:daichi703n:20170305150908p:plain

通常だと、以下のように差出人などの各項目に振り分け(フィルタ)対象を追加するだろう。この場合、項目内はOR条件になるが、項目間の関係はANDになってしまう。

f:id:daichi703n:20170305151739p:plain

項目間でOR条件を使用することは通常できないため、ここで、メッセージ ヘッダー内を使用する。

f:id:daichi703n:20170305151019p:plain

ここにメールアドレス件名(対象文字列)を追加することで、OR条件により振り分けがされる。

f:id:daichi703n:20170305152022p:plain

これにより、通常だと二つのルールを作成しなければならなかったような条件も一つにまとめられる。

まとめ - Outlookの振り分けルールでAND/OR条件を組み合わせる

Outlookでのメール振り分け条件としてメッセージヘッダー情報を使用することで、項目間のOR条件相当の振り分けフィルタルールを作成できる。

Ubuntu OSバージョンとkernelバージョンの対応表(17.04更新)

f:id:daichi703n:20170305141711p:plain

(2017/7/14 Version 17.04 Zesty Zapus の情報を追記)

Linuxの主要ディストリビューションの一つで、デスクトップ用途で広いシェアを持つUbuntu。各種ソフトウェアをインストールする際には、OSそのもののバージョンに加え、kernel(カーネル)のバージョンにも注意する必要がある。

UbuntuのOSバージョンとkernelバージョンの対応表を示す。

Ubuntu OSバージョンとkernelバージョン

Ubuntuのバージョンの歴史はこちらのWikipediaにまとまっている。(英語)

Ubuntu version history - Wikipedia

また、こちらで本内容と同じディスカッションがされている。

askubuntu.com

ここ最近でのバージョン対応は以下の通り。LTS versionでは新しいkernel versionをサポートしているものもある。これによりOSバージョンはそのまま新kernelの機能を使用することができる。

OS Ver OS Name kernel Ver
14.04 Trusty Tahr 3.13 or newer
14.10 Utopic Unicorn 3.16
15.04 Vivid Vervet 3.19
15.10 Wily Werewolf 4.2
16.04 Xenial Xerus 4.4 or newer
16.10 Yakkety Yak 4.8
17.04 Zesty Zapus 4.10

Ubuntuバージョン確認方法

UbuntuのOSバージョン及びkernelバージョンは以下の通り確認できる。次の例ではOSバージョン:14.04.5 LTS, kernelバージョン:4.8.4-c9となっている。先の表で言うor newerカーネルが使用されている。

$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.5 LTS"

$ uname -a
Linux <hostname> 4.8.8-c9 #1 SMP Mon Feb 13 03:16:28 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

まとめ - Ubuntu OSバージョンとkernelバージョンの対応表

UbuntuのOSバージョンとkernelバージョンの対応表は本文の通り。LTSではより新しいkernelバージョンも使用できる。

Express + Node.jsで別サイトにHTTP GETして結果を表示する

公開しているサーバが、他のサーバからアクセス(HTTP/S GET)可能な状態かを確認したいタイミングがあり、Express + Node.jsで簡易プログラムを作成した。これにより、APIへのアクセス確認、HTTPS(SSL)の証明書確認など、自身だけではできない確認ができる。ポイントはクライアントPCからではなく、サーバ(アプリケーション)自身からアクセスしていること。

確認できること

HTTP/Sの通信確認 (Webアプリケーション自身からGET)

StatusCodeとBodyを表示する。このような表示。

f:id:daichi703n:20170228222338p:plain

公開プログラム

Herokuにてプログラムを公開している。(フリープランなので立ち上がり遅い場合あり)

HTTP/S Checker - Heroku

できないこと・修正したい点

なお、エラーハンドリングは実装しきれておらず、HTTPSの通信ができないときはInternal Server Error (500)になってしまう…。また、form送信時に新規タブが立ち上がってしまったり、修正したいことは多々あり…。

随時修正して公開プログラムをアップデートしていきたい。

ソースコード

Express + Node.jsのソースコードはこちらで公開している。ご自由にお持ちください。

仕組みとしては、jadeのformで宛先URLを入力し、クエリとしてNode.jsで読み込む。与えられたURL(クエリ)に対してthen-requestモジュールでアクセスして各種情報を取得する。then-requestは同期処理ができないが今回は問題なく動作した。

まとめ - Express + Node.jsで別サイトにHTTP GETして結果を表示する

Express + Node.js then-requestモジュールにより、アプリケーション自身が別サイトにアクセスして結果を表示するプログラムを作成した。表示内容を編集することでAPIの動作確認等の用途に使用できる。