さくらVPSから自宅にVPN接続する

本日の内容はタイトル通りです。 Qiitaに投稿しようか迷ったんですが、ブログの方が残る気がするので、こっちに書こうと思います。半分、自分メモです。
まずは宅内の構成図を見ましょう。

赤線の部分が今回のVPN接続に関係する箇所です。さくらVPSに構築しているCentOS 7.7から、自宅に設置しているASA5520にVPNで接続し、宅内ネットワークに接続します。ASA5520の設定は、その説明を書くだけで膨大な文章になってしまうので、割愛します。CCNA Security程度の知識もしくはググる力があれば十分設定可能です。ASA5520は一般的にはFirewallとして認知されてると思いますが、VPN接続も可能です。
今回はさくらVPS(CentOS)の、接続用シェルスクリプトについてメモります。
ipsecやxl2tpdのインストールやCentOSの設定は済んでいる前提です。ググればインストールから設定まで出来ると思います。ただ実際に接続しようとすると、やれipsecを起動したりxl2tpdを起動したりroute addしたりする必要があって、いちいち一つずつコマンドを叩くのが手間なので、シェルスクリプト化しました。今回は備忘録として、接続・切断・接続確認用のシェルスクリプトについてメモっていきたいと思います。
追記(2019/10/26):スクリプトの一部を修正したので当記事にも反映しました。/etc/resolv.confを書き換える処理を追加しています。また、エラー判定をrcという変数に入れた後にif文でエラーの有無を判定していましたが、直接$?を見ることで判定するようにしました。

VPN接続用スクリプト(vpn_connect.sh)

#!/bin/bash

##---------------------------------------------------------
#
# 変数設定
#
##---------------------------------------------------------

script_name=`/bin/basename $0`
log_file="/var/log/vpn.log"

##---------------------------------------------------------
#
# 関数設定
#
##---------------------------------------------------------
function LOG() {
  /bin/echo -e "`date '+%Y-%m-%d_%H:%M:%S'` ${script_name}: $@" >> ${log_file}
  if [[ `/bin/echo $@ | grep "ERROR"` ]]; then
    /bin/logger -t ${script_name} $@
  fi
}

##---------------------------------------------------------
#
# メイン処理
#
##---------------------------------------------------------

# メイン処理開始宣言
LOG "[INFO] Starting VPN Connection..."
/bin/echo "[INFO] Starting VPN Connection..."

# VPN接続確認
/usr/local/src/vpn_status.sh
if [ $? -eq 0 ];then
  LOG "[INFO] VPN is already established."
  /bin/echo "[INFO] VPN is already established."
  exit 0
fi

# ipsecサービス開始
/bin/systemctl start ipsec
if [ $? -eq 1 ];then
  LOG "[ERROR] ipsec start failed."
  /bin/echo "[ERROR] ipsec start failed."
  exit 1
else
  LOG "[INFO] ipsec started."
  echo "[INFO] ipsec started."
fi

/usr/bin/sleep 1

# xl2tpdサービス開始
/bin/systemctl start xl2tpd
if [ $? -eq 1 ];then
  LOG "[ERROR] xl2tpd start failed."
  /bin/echo "[ERROR] xl2tpd start failed."
  exit 1
else
  LOG "[INFO] xl2tpd started."
  /bin/echo "[INFO] xl2tpd started."
fi

/usr/bin/sleep 1

# VPN接続フェーズ
/sbin/ipsec auto --up vpn-pine > /dev/null 2>&1
if [ $? -eq 1 ];then
  LOG "[ERROR] ipsec connect failed."
  /bin/echo "[ERROR] ipsec connect failed."
  exit 1
else
  LOG "[INFO] ipsec connect started."
  /bin/echo "[INFO] ipsec connect started."
fi

# ppp0インタフェースが存在しない場合のみ追加
/sbin/ip a | /bin/grep ppp0 > /dev/null 2>&1
if [ $? -eq 0 ]; then
  LOG "[INFO] ppp0 exists."
  /bin/echo "[INFO] ppp0 exists."
else
  LOG "[INFO] create ppp0 interface."
  /bin/echo "[INFO] create ppp0 interface."
  /bin/echo "c vpn-pine" > /var/run/xl2tpd/l2tp-control
fi

/bin/sleep 5

# VPN接続した際のローカルIPアドレスのルーティングを追加
/sbin/ip r | grep 192.168.0.0 > /dev/null 2>&1
if [ $? -eq 0 ]; then
  LOG "[INFO] route to 192.168.0.0/24 exists."
  /bin/echo -e "[INFO] route to 192.168.0.0/24 exists."
else
  LOG "[INFO] route add 192.168.0.0/24 dev ppp0."
  /bin/echo -e "[INFO] route add 192.168.0.0/24 dev ppp0."
  /sbin/ip route add 192.168.0.0/24 dev ppp0
fi

/bin/sleep 1

# DNSサーバのIPアドレスを/etc/resolv.confに追加
/usr/bin/grep '^nameserver 192.168.0.209' /etc/resolv.conf
if [ $? -ne 0 ];then
  /usr/bin/sed -i -e "2i nameserver 192.168.0.209" /etc/resolv.conf
  /usr/bin/sed -i -e "3i search pine.com" /etc/resolv.conf
  if [ $? -eq 0 ];then
    LOG "[INFO] Added DNS server to /etc/resolv.conf."
    /bin/echo -e "[INFO] Added DNS server to /etc/resolv.conf"
  fi
fi

# ルータに疎通確認することでVPN接続の確立を確認
/bin/ping -c 1 router > /dev/null 2>&1
if [ $? -eq 0 ]; then
  LOG "[INFO] VPN connected."
  /bin/echo -e "\e[1;32m [INFO] VPN connected. \e[m"
else
  LOG "[ERROR] VPN not connected."
  /bin/echo -e "\e[1;31m [ERROR] VPN not connected. \e[m"
fi

exit 0

VPN切断用スクリプト(vpn_disconnect.sh)

#!/bin/bash

##---------------------------------------------------------
#
# 変数設定
#
##---------------------------------------------------------

script_name=`/bin/basename $0`
log_file="/var/log/vpn.log"

##---------------------------------------------------------
#
# 関数設定
#
##---------------------------------------------------------
function LOG() {
  /bin/echo -e "`date '+%Y-%m-%d_%H:%M:%S'` ${script_name}: $@" >> ${log_file}
  if [[ `/bin/echo $@ | grep "ERROR"` ]]; then
    logger -t ${script_name} $@
  fi
}

##---------------------------------------------------------
#
# メイン処理
#
##---------------------------------------------------------

# メイン処理開始宣言
LOG "[INFO] Stopping VPN Connection..."
echo "[INFO] Stoopping VPN Connection..."

# 事前処理
echo "d vpn-pine" > /var/run/xl2tpd/l2tp-control

# VPN切断フェーズ
ipsec auto --down vpn-pine  > /dev/null 2>&1
if [ $? -eq 1 ];then
  LOG "[ERROR] ipsec disconnect had failed."
  echo "[ERROR] ipsec disconnect had failed."
  exit 1
else
  LOG "[INFO] ipsec disconnecting."
  echo "[INFO] ipsec disconnecting."
fi

# ipsecサービス停止
systemctl stop ipsec
if [ $? -eq 1 ];then
  LOG "[ERROR] ipsec stop failed."
  echo "[ERROR] ipsec stop failed."
  exit 1
else
  LOG "[INFO] ipsec stopped."
  echo "[INFO] ipsec stopped."
fi
sleep 1

# xl2tpdサービス停止
systemctl stop xl2tpd
if [ $? -eq 1 ];then
  LOG "[ERROR] xl2tpd stop failed."
  echo "[ERROR] xl2tpd stop failed."
  exit 1
else
  LOG "[INFO] xl2tpd stopped."
  echo "[INFO] xl2tpd stopped."
fi
sleep 1

# VPN切断
echo "d vpn-pine" > /var/run/xl2tpd/l2tp-control

# DNSサーバのIPアドレスを/etc/resolv.confから削除
/usr/bin/sed -i -e "/^nameserver 192.168.0.209$/d" /etc/resolv.conf
/usr/bin/sed -i -e "/^search pine.com$/d" /etc/resolv.conf
if [ $? -eq 0 ];then
    LOG "[INFO] Deleted DNS server from /etc/resolv.conf."
    /bin/echo -e "[INFO] Deleted DNS server from /etc/resolv.conf"
fi

# VPN切断確認
# ping -c 1 192.168.0.1 > /dev/null 2>&1
/bin/nslookup router > /dev/null 2>&1
if [ $? -ne 0 ]; then
  LOG "[INFO] VPN disconnected."
  echo -e "\e[1;32m [INFO] VPN disconnected. \e[m"
else
  LOG "[ERROR] VPN failed to disconnect."
  echo -e "\e[1;31m [ERROR] VPN failed to disconnect. \e[m"
fi

exit 0

VPN接続確認用スクリプト(vpn_status.sh)

#!/bin/bash

##---------------------------------------------------------
#
# 変数設定
#
##---------------------------------------------------------

script_name=`/bin/basename $0`
log_file="/var/log/vpn.log"
now_time=`date +%s`
l2tp_control_time=`ls -l --time-style='+%s' /var/run/xl2tpd/l2tp-control | cut -d" " -f 6`

# 時刻計算
vpn_time=`/bin/expr ${now_time} - ${l2tp_control_time}`
H=`/bin/expr ${vpn_time} / 3600`
vpn_time=`/bin/expr ${vpn_time} % 3600`
M=`/bin/expr ${vpn_time} / 60`
S=`/bin/expr ${vpn_time} % 60`

##---------------------------------------------------------
#
# 関数設定
#
##---------------------------------------------------------
function LOG() {
  /bin/echo -e "`date '+%Y-%m-%d_%H:%M:%S'` ${script_name}: $@" >> ${log_file}
  if [[ `/bin/echo $@ | grep "ERROR"` ]]; then
    /bin/logger -t ${script_name} $@
  fi
}

##---------------------------------------------------------
#
# メイン処理
#
##---------------------------------------------------------


# VPN接続確認
# ipsec auto --status > /dev/null 2>&1
/bin/ping -c 1 192.168.0.1 > /dev/null 2>&1
if [ $? -eq 0 ];then
  LOG "[INFO] VPN connected."
  /bin/echo -e "[INFO] VPN connected. (${H}:${M}:${S})"
  exit 0
else
  LOG "[INFO] VPN not connected."
  /bin/echo "[INFO] VPN not connected."
  exit 1
fi

exit 0

teratermでさくらVPSからVPN接続・自宅サーバにping・VPN切断してみる

今回はシェルスクリプトを/usr/local/src配下に格納してるのですが、Pathを通していますので、/usr/local/srcにcdしなくても実行可能です。
※ systemctlを使う都合で、root権限で実行する必要があります。

自宅にVPN接続することで何が便利なのか

  • さくらVPSを踏み台にすることで宅内環境(自宅サーバ、Windows、NASなど)に直接潜り込める。
  • さくらVPS以外にもiPhoneやMacBook AirからでもVPNで繋がるので、自宅の環境へアクセスしやすい。
  • 出先の環境で外部への接続がSSH(port 22)のみ許可されている場合、さくらVPSを踏み台としてSSH portforwardingで宅内のWindowsやNASにアクセスが可能。

余談:Cisco ASA5520の管理画面について

ASA5520の設定はコマンドラインからも可能なのですが、Cisco ASDMIDM Launcherを利用することでGUIからも設定が可能です。このランチャーの操作についてはCCNA Securityの問題で頻出するので見方や操作を覚える必要があります。(CCNA Securityの試験は2020年にCCNAとして一本化されるようなので、この画面を見ることは無くなってしまうかもしれませんが…)
画像では、VPN Sessionsの箇所で IPsec:1になっていますが、これはさくらVPSからVPN接続しているためです。

しつこいようですが自宅サーバについて語らせてください

インフラエンジニアともなると、自宅にサーバを立てて勉強するのは、よくあることですし、先輩からは「自宅サーバが勉強の近道」と言われるほど、自宅サーバは勧められることが多いです。
その背景には、自宅のサーバなので、環境を破壊しても金銭的な損害は発生せず、被害を受けるのは自分だけ、というのがあります。成功も失敗も含め思う存分やりたいことが出来るのが最大のメリットとなります。

今日はその中でも、僕が自宅で立てているサーバを紹介したいと思います。

ESXi6.7上に仮想マシンを立てる形で自宅サーバを構築しています。メモリは32GB積んでおり、自宅サーバとしては十分な容量です。サーバ本体はタワー型の「ProLiant ML310e Gen8 v2」です。
それでは、一つ一つのサーバ(仮想マシン)について紹介していきます。

  • bind →内向けのDNSサーバ (CentOS7)
  • docker → Docker勉強用
  • kaede → 踏み台からVPN接続からこなすなんでも屋 (CentOS7)
  • vbat → ansibleなどの自動化用サーバ
  • vlog → 各サーバやNW機器からのログをSNMPで一元収集している。
  • vmwin → Windows踏み台(Win10)
  • zabbix4 → Zabbix4系の監視専門サーバ、監視データを蓄積し、可視化する。異常が発生するとLINEに通知する仕組みを導入している。また、監視を視覚的に行うことが出来るよう、Grafanaを導入している。

以上でございます。
メールサーバやファイルサーバなど、立てようと思えば色々あるのですが、メンテナンスが煩雑になることや、最近は特に、自前で構える必要が無くなってきていることから、現状はこれで満足しています。不要と感じるサーバは立てない方が賢明です。逆に、今後必要と思われるサーバがを立てる必要が出てきたら、適宜追加を予定しています。(メールについては、近々動かしてみたいなと思っています)
なお、NTPサーバは仮想マシンで立てるのはNGというのが業界の常識です。理由として、仮想マシンは物理サーバと比べ時刻のズレが著しいので、仮想マシンでNTPサーバを立てると時刻のズレが大きく生じてしまいます。ですので、NTPサーバは物理サーバに立てることが圧倒的に多いです。
また、自宅サーバではあまり無いかと思いますが、大きなメモリ(512GBなど)が求められるDBサーバなども物理サーバに立てることが一般的です。一般的なご家庭の自宅サーバでそこまでのメモリ容量を求められることはないと思いますが…データセンタだと見かけることが、ままあります。

Windows Serverのライセンスに余裕があるよって方は、Windows ServerにADサーバを立てて、普段使ってるパソコンをドメイン参加させると、Windowsのドメインについてより詳しくなれるかと思います。ADは色んな現場で使われる技術ですので、習得しておくと今後の理解が楽だと思います。

でもな、WindowsServer高いんだよなぁ。。。

体調が芳しくない

先日、徹夜で仕事に行ったら、昼休み中に倒れて救急搬送されてしまいました。いやぁ…やっちまったぜ。搬送先の病院で一通り救急検査を受けたのですが、意識も正常に戻っていたし普通に歩けたので、帰されました。
その後、実家近くの病院に行ったのですが、問診だけでは診断が確定出来なかったため、精密検査をすることになりました。病院の都合で来月に検査を行うことになったので、それまでは大人しく過ごすことになりそうです。

仕事についですが、色々と話し合った結果、今の現場は退場することになりました。現場も僕も、退場じゃなくて継続の方向だったんですが、仲介会社さんがNGでした。残念。。。まぁ仕事中に倒れた身なので何も言えないですね。健康第一ですね、本当。

もう高校くらいから不眠体質なんですが、さすがに徹夜は体がもたないですね。でも眠くても寝れない時ってあるんだよねぇ。難しいねぇ。