Cisco 機器と IPSec その4

今回は、 NAT-Traversalなやつです。 ルーターがespとかudp500とかudp4500を固定的に割り当ててくれなくても大丈夫なやつです。

この構成だと、Side-B 側がかならずinitiatorになります。 Side-Aから接続しにいっても500番ポートとか開いてませんので。

Site-A はグローバルIPアドレスを所持。 Site-B はグローバルIPアドレスを持った機器の配下にぶら下がっている機器がNAPTでインターネットに出られるような構成でSite-A - Site-B のIPSec Tunnelを張ります。

(SecmentA)Site-A[GlobalPv4Address] -- Internet -- [GlobalIPv4Address]Router[LocalIPv4Address] - [LocalIPv4AddressSite-B(SegmentB)

ここで Site-A ===tunnel=== Site-B でトンネルを張ってSegmentAとSegmentBの通信を行います。

(192.168.100.0/24)Site-A[200.0.0.2] -- [200.0.0.1]Router[192.168.10.1/24] - [DHCP]SiteB(192.168.200.0/24)

こんな感じとしましょう。

設定

Route

ip dhcp pool test
   network 192.168.10.0 255.255.255.0
   default-router 192.168.10.1
   lease 30

interface GigabitEthernet0/0/0
 ip address 192.168.10.1 255.255.255.0
 ip nat inside

interface GigabitEthernet0/0/1
 ip address 200.0.0.1 255.255.255.0
 ip nat outside

ip nat inside source list 10 interface FastEthernet0/1 overload
access-list 10 permit 192.168.10.0 0.0.0.255

Site-A

crypto isakmp policy 1
 encr aes
 authentication pre-share
 group 2

crypto isakmp key cisco address 200.0.0.1

crypto ipsec transform-set IPSEC-SET esp-aes esp-sha-hmac

crypto ipsec profile VTI-PROFILE
 set transform-set IPSEC-SET
 set pfs group2

interface Tunnel1
 ip unnumbered FastEthernet0/0
 ip ospf 1 area 0
 tunnel source FastEthernet0/0
 tunnel destination 200.0.0.1
 tunnel mode ipsec ipv4
 tunnel protection ipsec profile VTI-PROFILE

interface GigaibitEthernet 0/0/0
 ip address 200.0.0.2 255.255.255.0

interface GigabitEthernet 0/0/
 ip address 192.168.100.1 255.255.255.0
 ip ospf 1 area 0

Site-B

crypto isakmp policy 1
 encr aes
 authentication pre-share
 group 2

crypto isakmp key cisco address 200.0.0.2

crypto ipsec transform-set IPSEC esp-aes esp-sha-hmac

crypto ipsec profile VTI
 set transform-set IPSEC
 set pfs group2

interface Tunnel1
 ip unnumbered FastEthernet0/0
 ip ospf 1 area 0
 tunnel source FastEthernet0/0
 tunnel destination 200.0.0.2
 tunnel mode ipsec ipv4
 tunnel protection ipsec profile VTI

interface GigabitEthernet0/1
 ip address dhcp
interface GigabitEthernet0/2
 ip address 192.168.200.1 255.255.255.0
 ip ospf 1 area 0

実験

上記設定を見ると、Side-A側からみると、Side-B側の対向端末は特定できていないことに気づきます。

例えば下記のような設定を持つSide-B-2 みたいなのを用意したらどうなるのかという問題です。

Side-B-2

crypto isakmp policy 1
 encr aes
 authentication pre-share
 group 2

crypto isakmp key cisco address 200.0.0.2

crypto ipsec transform-set IPSEC esp-aes esp-sha-hmac

crypto ipsec profile VTI
 set transform-set IPSEC
 set pfs group2

interface Tunnel1
 ip unnumbered FastEthernet0/0
 ip ospf 1 area 0
 tunnel source FastEthernet0/0
 tunnel destination 200.0.0.2
 tunnel mode ipsec ipv4
 tunnel protection ipsec profile VTI

interface GigabitEthernet0/1
 ip address dhcp
interface GigabitEthernet0/2
 ip address 192.168.210.1 255.255.255.0
 ip ospf 1 area 0

試しに足してみましょう。

(SecmentA)Site-A[GlobalPv4Address]  -- Internet  -- [GlobalIPv4Address]Router[LocalIPv4Address] - [LocalIPv4AddressSite-B(SegmentB)
                                                                                                - [LocalIPv4AddressSite-B-2(SegmentC)

すると、 Routerでは

#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
udp 200.0.0.1:1        192.168.10.2:500   200.0.0.2:500      200.0.0.2:500
udp 200.0.0.1:4500     192.168.10.2:4500  200.0.0.2:4500     200.0.0.2:4500
udp 200.0.0.1:1024     192.168.10.3:4500  200.0.0.2:4500     200.0.0.2:4500

例えばこんなnatテーブルが出来上がります。

(10.2=Side-B, 10.3=side-B-2)

Side-A 側では

#sh ip ospf nei
Neighbor ID     Pri   State           Dead Time   Address         Interface
192.168.10.2      0   FULL/  -        00:00:30    192.168.10.2    Tunnel1

#sh ip ospf nei
Neighbor ID     Pri   State           Dead Time   Address         Interface
192.168.10.3      0   FULL/  -        00:00:37    192.168.10.4    Tunnel1

と、ospf のneighborが変わりました。

既にIPSecでつながっている状態でさらに割り込もうとすると、後から接続しにいったほうとIPSecを張り直します。 のでこのようなことに。

どうでもいいこと

ResponderをPaloaltoにしようとすると、Initiator 側のローカルIPアドレスを固定する必要があります。

Live Community - IPSec VPN Tunnel with NAT Traversal - Live Community

ResponderがCiscoであった場合に出ていた上記のような問題は起きないと考えてよさそうです。

prometheusの remote write (influxdb)

はじめに

prometheusは、データを永続的に保管する目的で使うのはあんまりよくないと書かれています。

If your local storage becomes corrupted for whatever reason, your best bet is to shut down Prometheus and remove the entire storage directory.

では永続的に保管するにはどうするかというと、remote writeというリモートストレージにデータを書き込む方法が提供されています。

対応しているリモートストレージの一覧がドキュメントに記載されています。 念のために列挙しますと以下の通りです。

  • AppOptics: write
  • Chronix: write
  • Cortex: read and write
  • CrateDB: read and write
  • Gnocchi: write
  • Graphite: write
  • InfluxDB: read and write
  • OpenTSDB: write
  • PostgreSQL/TimescaleDB: read and write
  • SignalFx: write

このうち、今回はInfluxDBを試してみました。

InfluxDB へ remote writeする

InfluxDBへremote write する方法は2つあります。

  • prometheusが提供している remote_storage_adapterを利用する方法
  • InfluxDBが対応している prometheusのremote write 向けAPIを利用する方法

使うとどのようになるのかをそれぞれ実験してみます。

prometheusが提供している remote_storage_adapterを使う方法

remote_storage_adapter というものがPrometheusオフィシャルで提供されているのでそれを利用します。

利用方法は オフィシャルに記載がある通りなのですが、

remote_storage_adapter をビルドし、 2つのオプション

を指定して起動します(ここではローカルにInfluxDBが動いている前提で書かれています)。

./remote_storage_adapter -influxdb-url=http://localhost:8086/ -influxdb.database=prometheus

次に、prometheusのremote_write設定に remote_storage_adapter を指定します。

remote_write:
  - url: "http://localhost:9201/write"

この状態でPrometheusをreloadすると、InfluxDBにデータが送信され始めます。(remote_write_adapterはデフォルトでは9201番ポートをListenします)

  • InfluxDBが提供しているAPIを利用する

InfluxDBのドキュメントに記載されている方法を利用します。

1つ目の方法と違い、PrometheusとInfluxDBのほかに用意する必要はありません。

prometheusのremote_write設定にInfluxDBを指定するだけで良いです。

remote_write:
  - url: "http://localhost:8086/api/v1/prom/write?db=prometheus"

この状態でPrometheusをreloadすると、InfluxDBにデータが送信され始めます。

remote_write されたデータを確認する

InfluxDB上のデータを確認してみます。

prometheusが提供している remote_storage_adapterを使う方法

$ influx
> use prometheus
> show series

とテーブルを見てみると、メトリック名でテーブルが作られているのがわかります。

> select * from tsdb_wal_fsync_duration_seconds
name: tsdb_wal_fsync_duration_seconds
time                instance       job        quantile value
----                --------       ---        -------- -----
1513046600853000000 localhost:9090 prometheus 0.5      0.001505024
1513046600853000000 localhost:9090 prometheus 0.9      0.001505024
1513046600853000000 localhost:9090 prometheus 0.99     0.001505024
1513046615853000000 localhost:9090 prometheus 0.5      0.000018808
1513046615853000000 localhost:9090 prometheus 0.9      0.001161131
1513046615853000000 localhost:9090 prometheus 0.99     0.001161131
1513046630853000000 localhost:9090 prometheus 0.5      0.001161131
1513046630853000000 localhost:9090 prometheus 0.9      0.001505024
1513046630853000000 localhost:9090 prometheus 0.99     0.001505024
1513046645853000000 localhost:9090 prometheus 0.5      0.001161131
1513046645853000000 localhost:9090 prometheus 0.9      0.001505918
1513046645853000000 localhost:9090 prometheus 0.99     0.001505918
1513046660853000000 localhost:9090 prometheus 0.5      0.000883545
1513046660853000000 localhost:9090 prometheus 0.9      0.001505918
1513046660853000000 localhost:9090 prometheus 0.99     0.001505918
1513046675853000000 localhost:9090 prometheus 0.5      0.000801818
1513046675853000000 localhost:9090 prometheus 0.9      0.001505918

このように、ちゃんと15秒ごとにデータがたまっているのがわかります。

  • InfluxDBが提供しているAPIを利用する
$ influx
> use prometheus
> show series

とテーブルを見てみると、_という名称でテーブルが作られているのがわかります。メトリック名はname に入っていますね。

> select  * from _ where __name__='tsdb_wal_fsync_duration_seconds'
name: _
time                __name__                        branch call code dialer_name endpoint event f64         goversion handler instance       interval job        le listener_name method quantile queue reason revision role rule_type scrape_job slice version
----                --------                        ------ ---- ---- ----------- -------- ----- ---         --------- ------- --------       -------- ---        -- ------------- ------ -------- ----- ------ -------- ---- --------- ---------- ----- -------
1512977394388000000 tsdb_wal_fsync_duration_seconds                                             0.001899241                   localhost:9090          prometheus                         0.5
1512977394388000000 tsdb_wal_fsync_duration_seconds                                             0.001899241                   localhost:9090          prometheus                         0.99
1512977394388000000 tsdb_wal_fsync_duration_seconds                                             0.001899241                   localhost:9090          prometheus                         0.9
1512977409388000000 tsdb_wal_fsync_duration_seconds                                             0.001188145                   localhost:9090          prometheus                         0.99
1512977409388000000 tsdb_wal_fsync_duration_seconds                                             0.001188145                   localhost:9090          prometheus                         0.9
1512977409388000000 tsdb_wal_fsync_duration_seconds                                             0.000020984                   localhost:9090          prometheus                         0.5
1512977424389000000 tsdb_wal_fsync_duration_seconds                                             0.001188145                   localhost:9090          prometheus                         0.9
1512977424389000000 tsdb_wal_fsync_duration_seconds                                             0.000938485                   localhost:9090          prometheus                         0.5
1512977424389000000 tsdb_wal_fsync_duration_seconds                                             0.001188145                   localhost:9090          prometheus                         0.99
1512977439388000000 tsdb_wal_fsync_duration_seconds                                             0.000938485                   localhost:9090          prometheus                         0.5
1512977439388000000 tsdb_wal_fsync_duration_seconds                                             0.001899241                   localhost:9090          prometheus                         0.99
1512977439388000000 tsdb_wal_fsync_duration_seconds                                             0.001899241                   localhost:9090          prometheus                         0.9
1512977454388000000 tsdb_wal_fsync_duration_seconds                                             0.001899241                   localhost:9090          prometheus                         0.99
1512977454388000000 tsdb_wal_fsync_duration_seconds                                             0.001899241                   localhost:9090          prometheus                         0.9
1512977454388000000 tsdb_wal_fsync_duration_seconds                                             0.000935074                   localhost:9090          prometheus                         0.5
1512977469389000000 tsdb_wal_fsync_duration_seconds                                             0.008376216                   localhost:9090          prometheus                         0.9
1512977469389000000 tsdb_wal_fsync_duration_seconds                                             0.000935074                   localhost:9090          prometheus                         0.5
1512977469389000000 tsdb_wal_fsync_duration_seconds                                             0.008376216                   localhost:9090          prometheus                         0.99

このように、ちゃんと15秒ごとにデータがたまっているのがわかります。 InfluxDBオフィシャルの実装を利用する場合は select * で検索すると残念な見た目になるので、ちゃんと 利用するタグを指定する必要がありそうです。

終わりに

Prometheusのremote write機能を利用してInfluxDBへデータを保存する方法を確認しました。

Prometheus側で用意した実装とInfluxDB側で用意した実装では、格納のされ方が違うので、互換性がないことがわかりました。どちらの方法を使うかはきちんと決めてから利用しましょう。

windows 10 fall creators update でなんか環境変数が設定しにくくなった気がするのでPowerShellで環境変数を設定することにしたっぽい。

[Environment]::GetEnvironmentVariable(<環境変数名>,[EnvironmentVariableTarget]::User)

で現在の値がゲットできる。

[Environment]::SetEnvironmentVariable(<環境変数名>,<値>,[EnvironmentVariableTarget]::User)

でセットできる。

pathを追加する場合は

[Environment]::SetEnvironmentVariable("path",[Environment]::GetEnvironmentVariable("path",[EnvironmentVariableTarget]::User)+<値>,[EnvironmentVariableTarget]::User)

こんな感じ。