グローバルIPアドレスがないけどNASを外部に公開したい

現在住んでいるマンションには無料で使える(管理費に含まれている)ネット環境があり、各部屋まで回線が来ているのですが、グローバルIPアドレスがもらえません。グローバルIPアドレスをもらえるようなオプションもなく、お金を払えばいいというわけでもないです。出先とかでNAS自宅サーバ)のデータを取得したりいじって遊びたいとか思ってもそのままではできないので、多少のお金を払うことで実現することにしました。

VPSを借りる

VPSというのは、バーチャル・プライベート・サーバの略で、仮想的な専用サーバをレンタルできるサービスです。専用サーバというと高いイメージがあったのですが、月500円くらいで借りることができます。

VPSならDTI|月額467円(税抜) メモリ1GB|ServersMan@VPS

基本的に自分の用途でしたら、一番安いプランで十分でした。安いプランでも固定IPアドレスをもらうことができます。

このVPSサーバにVPNサーバを立ててNASVPNクライアントとして接続することで、外部からVPSサーバに経由でNASにアクセスできるようにします。 

(2020年7月追記)

現時点ではAWS lightsailがおすすめです。3.5$か5$のプランで性能的には十分と思います。

 

VPSVPNサーバを設定する。

まずは、VPSの設定をします。

ServersMan@VPNでは、初期に入れるOSを選択することが可能ですが、今回はUbuntu 14.04を入れました。契約するとあっという間にセットアップが終わって、SSHでログイン出来るようになりますした。すごい。

UbuntuへのOpenVPNのインストールは公式ドキュメントに沿って進めます。

How To | OpenVPN.JP

apt-getでインストール可能です。必要そうなペッケージも同時にインストールします。

sudo apt-get install openvpn libssl-dev openssl easy-rsa

次に、サーバの認証局・証明書の設定をします。

OpenVPNの認証方式ですが

  • 静的鍵方式
  • パスワード認証
  • 認証書認証
  • 二要素認証

という4種類があります。基本的には、下に行くほどセキュリティは高まる一方、設定は面倒になります。認証書証明の設定を紹介するサイトが多いですが、プライベートな使用ではそこまでセキュリティを高めなくていいと思われますので、今回はパスワード認証を採用します。

OpenVPNの証明書について

パスワード認証を採用します、サーバ側の証明書については用意しておきます。ASUSTOR NASだとサーバ側の証明書を設定しないとうまくいかなかったので(正確には、認証局の情報がないとエラーとして弾かれてしまった)、、、

サーバ側の証明書の目的はサーバのなりすまし防止です。「自分のサーバと思って接続したOpenVPNのサーバが実は悪意を持ったサーバでパスワードなどを抜かれてしまった・・」というようなことを防ぐためです。

設定することは以下の通りです。

  • サーバにプライベート認証局を作る
  • プライベート認証局の証明書をクライアントとシェア
  • サーバの証明書をプライベート認証局に発行してもらう

ちなみに、プライベートな認証局の証明書でなりすましを防げる仕組みについて・・。接続時には、以下の手順を踏んでなりすましサーバでないことをクライアントで確認します。

  1. サーバからサーバ証明書を受け取る
  2. サーバ証明書が、プライベート認証局の証明書で署名されてものかを、事前にシェアされたプライベート認証局の証明書を使って確認
  3. サーバ証明書に含まれている公開鍵情報を元にランダムな数値を暗号化してサーバに送信。サーバはサーバ証明書とセットの秘密鍵を元にランダムな数値を複合かしてクライアントに送り返す。
  4. クライアントは正しい数値が送り返されることで、サーバが秘密鍵を持っていることを確認できるので、なりすましではないことを確認できる。

事前に認証局の証明書を信頼できる方法で受け取っておくことで認証局の信頼性は担保できますので、プライベートな認証局でも十分ということになります。

認証局の証明書とサーバ証明書の発行

まず、認証局の作成です。OpenVPNが配置されているディレクトリのeasy-rsaサブディレクトリに入れるのがいいようです。

/etc/openvpn/の下にサブディレクトリを以下のコマンドでつくります。

sudo make-cadir /etc/openvpn/easy-rsa

easy-rsaフォルダにある、varsというファイルを書き換えます。

(viを使うなら、sudo vi /etc/openvpn/easy-rsa/vars)

export KEY_COUNTRY="(国)"
export KEY_PROVINCE="(都市)"
export KEY_CITY="(街)"
export KEY_ORG="(組織名)"
export KEY_EMAIL="(メールアドレス)"
export KEY_OU="(組織単位らしいので適当に)"

あたりを適切な情報に修正します。これらの情報は、認証局の証明書に埋め込まれます。

その上でvi /etc/openvpn/easy-rsaに移動し、以下のコマンドを実行して、証明局を初期化、認証局の証明書(ca.crt)を発行します。

source vars
./clean-all
./build-dh
./pkitool --initca

次にサーバ用の証明書を発行します。

./pkitool --server server
./build-key-server server

 

easy-rsaフォルダに

ca.crt

ca.key

server.crt

server.key

というファイルができていると思いますので、これらは、

/etc/openvpn/

にコピーしておきます。(後ほど設定ファイルからこれらのファイルを参照するので、設定ファイルで絶対パスを書いておけば、別のフォルダにおいても問題ないはずです)

OpenVPNサーバ設定ファイル

次に、サーバ側の設定ファイルを記述します。

基本的には、

https://www.openvpn.jp/document/how-to/#SampleConfigurationFiles

を元に編集します。

 

今回は、次のような構成ファイルを作成して、server.confとして保存します。

上で書いたようにパスワード認証方式になります。

# 使用するポート
port 1194

# TCPUDP か
proto udp

# ブリッジモードを使用する必要がなければtunを選択
dev tun

# 認証局の証明書、および、サーバの証明書+秘密鍵
ca ca.crt
cert server.crt
key server.key # これが秘密鍵になるので公開しない

# Diffie hellman parameters.作成したものを指定
dh dh2048.pem

# VPNで使用するアドレス空間
# サーバは先頭のアドレス(10.8.0.1)が選ばれるようです
server 10.8.0.0 255.255.255.0

# サーバに接続してきたクライアントに対し
# 10.8.0.*のアドレスへのアクセスはVPNを通すように、設定を送る
push "route 10.8.0.0 255.255.255.0"

# クライアント同士も通信できるようにする
client-to-client

# 10秒ごとpingを送り120秒反応がなければ切断と判断
keepalive 10 120

# 暗号形式を指定。クライアントと合わせる必要がある
cipher AES-256-CBC # AES

# 圧縮を有効にする。クライアントと合わせる必要がある
comp-lzo

# 切断が発生したときの再接続などのためにクライアントと両方に以下設定しておくといいみたい
persist-key
persist-tun

# 現在のステータスを出力してくれる
status openvpn-status.log

# ログの出力先。
log-append /var/log/openvpn.log
# ログの出力レベル。数が多いほどいっぱい出力される。0〜9
verb 4

# パスワード認証するための設定。ログインユーザ名とパスワード名をそのままVPNのユーザ名とパスワードに使う
plugin /usr/lib/openvpn/openvpn-plugin-auth-pam.so login
# クライアントの証明書を不要にする
client-cert-not-required

これを/etc/opnevpn/フォルダにsercer.confという名前で保存します。

これで、OSのユーザアカウントとパスワードで接続できるようになります。NASから接続するためのアカウントとして、 OSのアカウントを作っておくようにします。基本的には一つのアカウントからは同時に1つしかVPNに接続できません。

クライアント設定ファイル

次に、クライアントの設定ファイルを用意します。

ASUSTOR NASむけに設定ファイルを使用する場合、認証局の証明書(ca.crt)は設定ファイルからファイル名を指定する形式ではなく、<CA>タグとして設定ファイル中に、証明書の中身を記述する必要があるようです。

 

# クライアント用の設定
client

# サーバと合わせる
dev tun
proto udp
persist-key
persist-tun
comp-lzo
cipher AES-256-CBC

# サーバのアドレス+ポート
remote 12.34.56.77 1194

# ノートPCなど常時接続していない環境向け設定。ホストに繋げられなくても諦めず何度も試す
resolv-retry infinite

# 特定のポートと紐づけるか。通常nobindでOKみたい
nobind

#以下、ca.crtの中身(ca.crtはテキストファイルなのでエディタで開いて貼り付け)
<CA>
-----BEGIN CERTIFICATE-----
MI(略)

(略)

(略)xoMsdw=
-----END CERTIFICATE-----
</CA>

# パスワード認証する
auth-user-pass

# Set log file verbosity.
verb 3
# ログの出力先
log-append /var/log/openvpn.log
# Silence repeating messages ;mute 20

これをVPN Clientに読み込ませて接続することになります。

ASUSTOR NAS AS3102Tでの設定

ASUSTOR NASにはデフォルトでOpenVPNの機能が入っています。

Webの管理ページの「設定」から「VPN」を選び、「追加」をクリックします。

接続タイプとして「OpenVPN」を選び、「OpenVPNプロバイダーから構成ファイルをインポートする」を選択します。

名前は、識別用なので自由に設定します。 アカウント、パスワードは、先ほど設定したNAS用のアカウントのものをいれ、「ファイルをインポート」で、先ほど作成したクライアント用の設定ファイルを指定してください。

これで設定は完了です。

接続をクリックして、接続できることを確認します。

NASsshでログインして、pingで10.8.0.1(VPNサーバ)へ通れば無事成功です。うまくいかない場合は、クライアント、サーバ双方のログを見ながら解決していくことになります。

 

上記の設定で、VPSsshでログインし、そこからさらにNASにアクセすれば、一応外部からNASへアクセス可能になりました。

ただ、例えばVPSのアドレスへhttpで(80番ポートに)接続したら、VPSではなくNASのレスポンスを返したい、といったこをするためには、ルータのポートフォワーディングみたいなことを、VPSサーバで行う必要があります。

そのためにはまず、NASが接続した時のVPN側アドレスを固定にしないと不便です。

OpenVPNでパスワード認証で接続した時、特定ユーザに固定IPを付与する方法

VPNサーバ側の設定変更が必要になります。

OpenVPNの機能として、クライアントのcommon nameに応じて固定IPを割り振ることができます。ただ、そのままの設定ではユーザ名がcommon nameにならないので、server.confに次の一行を追加します、

username-as-common-name

その上で、次の一行も追加します。

client-config-dir ccd

クライアントごとの設定がccdに入っていますよ、という意味になります。

クライアントごとの設定ファイルの場所として

/etc/openvpn/ccd

が指定されたととになりますので、このフォルダを作成し、ここにユーザ名をファイル名にしたテキストファイル(ユーザ名がnasならば、nasという名前のファイル)を作成します。

そのファイルには、例えばIPアドレスを10.8.0.100に指定したい場合、

ifconfig-push 10.8.0.100 10.8.0.99

というように記述します。10.8.0.99は別になんでもいいのですが、tunの場合、インターフェースに別のIPアドレスが必要になりますので、インターフェースのIPも別途指定する必要があるためこのような記述になります。

こうして、OpenVPNサーバを

service openvpn restart

などとして再起動し、クライアントから再度接続すれば10.8.0.100が割り振られるようになります。

 

VPSの特定のポートにきた通信を、特定IPの別マシンにフォワードする方法

ルータのポートフォワーディングみたいなことをVPSで行う方法です

iptablesを使うことになります。

iptablesは詳細な説明は避けます。すみません。

例えば、VPS(仮にグローバルIPを12.34.56.78とします. VPN側は10.8.0.1)の8080番ポートにきたものをNAS(10.8.0.100)の80番ポートに流す場合、次のようなコマンドを打ちます。

iptables -t nat -A PREROUTING -m tcp -p tcp --dst 12.34.56.78 --dport 8080 -j DNAT --to-destination 10.8.0.100:80

iptables -t nat -A POSTROUTING -m tcp -p tcp --dst 10.8.0.100 --dport 80 -j SNAT --to-source 10.8.0.1

一行目が、8080番ポートにきた通信を、NASの80番ポートに流す設定

二行目が、その通信の送り元を10.8.0.1(VPSVPNアドレス)にするという設定です

また、そもそものiptablesの設定として、基本ポートへの接続を受け付けない設定になっていることがあります。

iptables -L

とうって、INPUT /OUPUTなどがpolicy ACCEPTになっていることを確認します。

もし、意図してDROPしている場合は、特定のポートを受信できるようにしておく必要があります。

こうすることで、 ルータのポートフォワーヂングのような形で、VPSの特定ポートへのアクセスをNASに渡すことができるようになります。

 

こうすることで、NASのWebサーバを外部に公開するといったことが可能になります!