たった一つのコマンドで自動でVPN接続とSSH接続し、計算サーバーにログインする。

# Abstract
### 現状
私は通常、計算サーバーを利用するために、Cisco AnyConnect Secure Mobility ClientのGUIによってVPN接続を行い、ターミナル上でSSH接続を行っていた。そして、その都度コマンドやパスワードを求められることに煩わしさを感じていた。
<img width="500" alt="cisco.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613755/9ea5afaf-b473-6825-a9cb-2f3d785e38f1.png">


### 目標
たった一つのコマンド、例えば

```terminal:
$ con
```
と打つだけでCisco AnyConnect Secure Mobility ClientによるVPN接続とSSH接続を自動で完了し、計算サーバーに自動でログインできるようにする。

# 環境
・MacBook Pro（2020）
・OS：macOS Big Sur
・シェル：zsh
・VPNクライアントソフト：Cisco AnyConnect Secure Mobility Client (version 4.9.01095)

# 自動でVPN接続を行うコマンド
自動でVPN接続を行うために、コマンドをシェルスクリプトにまとめ、aliasを作成する。また、ユーザー名やパスワードを自動入力するために、```expect```コマンドを使う。

### expectコマンドを導入する。

```terminal:
$ brew install expect
```

・```expect -c```：```"  "```で囲まれた```expect```の拡張コマンドを上から実行していく。
・```spawn```：シェルスクリプト内で初めに実行されるコマンド。
・```expect```：```spawn```を実行した際に表示されると想定される文字列（```Password:```など）を表す。文字列は```\"```と```"\```で囲む必要がある。
・```send```：```expect```で想定された文字列が来た際に、入力する文字列（パスワード）を表す。


### VPN接続のためのシェルスクリプト
ターミナル上でCisco AnyConnect Secure Mobility Client経由のVPN接続を行うためには、コマンド```/opt/cisco/anyconnect/bin/vpn connect```を使う。

```zsh:~/.vpn_sample.sh
#!/bin/sh

# タイムアウト設定
set timeout=10
# 接続先エイリアスまたはIPアドレス
CONNECTION_ALIAS=sample@hoge.com
# ユーザー名
USER_NAME='vpn_username'
# パスワード
PW='vpn_pass'

expect -c "
    spawn /opt/cisco/anyconnect/bin/vpn connect ${CONNECTION_ALIAS}
    expect \“Username:\”
    send \"${USER_NAME}\n\"
    expect \"Password:\"
    send \"${PW}\n\"
    expect \"state: Connected\"
    exit 0
"
```

### aliasの設定
最後に、```~/.zshrc```に

```bash:~/.zshrc
#VPN接続するためのコマンド
alias vpn_sample='source vpn_sample.sh'

#VPN接続を解除するためのコマンド
alias disvpn='/opt/cisco/anyconnect/bin/vpn disconnect'
```
を追記すると、

```terminal:
$ vpn_sample
```
というコマンドでVPN接続できる。また、

```terminal:
$ disvpn
```
で接続解除できる。

###注意
Cisco AnyConnect Secure Mobility Clientのアプリを終了する必要がある。起動している場合、

```shell-session:
send: spawn id exp6 not open
    while executing
```
というエラーが出る。

# 自動でSSH接続を行うコマンド
CLIで行っていたSSH接続をシェルスクリプトにまとめる。ここでも、```expect```を用いる。

### SSH接続のためのシェルスクリプト
```zsh:~/.ssh_sample.sh
#!/bin/sh

PW='ssh_pass'

expect -c "
    spawn ssh (option) hoge@example.com
    expect \"Password:\"
    set timeout 1
    send \"${PW}\n\"
    interact
"
```
###aliasの設定

```bash:~/.zshrc
#SSH接続するためのコマンド
alias ssh_sample='source ssh_sample.sh'
```
以上を```~/.zshrc```に追記する。VPN接続を完了させ

```terminal:
$ ssh_sample
```
とするとSSH接続ができる。

# VPN接続&SSH接続のaliasを作成

複数コマンドのaliasを作成するために```function```を使う。
ここまでに示した```~/.zshrc```の変更点をまとめる。

```bash:~/.zshrc
#VPN接続するためのコマンド
alias vpn_sample='source vpn_sample.sh'

#SSH接続するためのコマンド
alias ssh_sample='source ssh_sample.sh'

#SSH接続を切断するコマンド
alias discon='/opt/cisco/anyconnect/bin/vpn disconnect'

#VPN接続とSSH接続を一度に行う
function con() {
    vpn_sample;
    ssh_sample;
}
alias con=con
```
# まとめ
以上の```~/.vpn_sample.sh```、```~/.ssh_sample.sh```、```~/.zshrc```の設定により、

```terminal:
$ con
```
だけで計算サーバーに自動でログインできるようになり幸せになった。
# 参考にしたサイト
#### expectコマンドの導入
https://qiita.com/auto_masanori/items/207412d409fb9971ab43
#### Cisco AnyConnect Secure Mobility Clientをターミナル上で操作する。
https://qiita.com/mamohacy/items/bcd3f575a9555d2f18a4
#### シェルスクリプトでSSH接続する。
https://dot-blog.jp/news/shellscript-mac-terminal-command-auto/
#### 複数コマンドのaliasを作成する。
https://qiita.com/mikakane/items/ac27582e8e52228adced

#追記
Ubuntu 20.04 LTSでも動作することを確認しました。