プロキシのストレスをちょっと減らす for Linux

この記事は この記事は、Kogakuin Univ Advent Calendar 2018 の25日目です。 昨日は 研究室のサーバに接続したい です。

弊学のネットワークはプロキシ必須で苦しいですよね。ストレスMAXですよね。
特にラップトップにLinux入れて持ち歩いてる人は大変ですよね、GUICLIのそれぞれでプロキシの設定が必要なので大変ですよね。

この記事はLinuxの面倒なプロキシ切り替えを自動化する方法を書きます。
自動切り替えの対象は主にGUI(chrome系ブラウザ)、CLISSHです。
環境はArchLinux, Plasma, Zshですが細部をちょっと変更すれば動くはずです。

GUI

Gnome系やPlasma(KDE)系のデスクトップには以下のようなProxyの設定画面が用意されています。
f:id:u10e10:20181225221654p:plain

少し前のChrome系のブラウザはGUIのプロキシ設定ではなく、起動時に環境変数でプロキシの設定を渡す必要がありました。
最近はGUIの設定を見てくれるので、プロキシ設定のためにブラウザを再起動する必要がなくなりました。

さて、GUIのプロキシの設定ですが、いちいち手動で設定を切り替えるのは面倒です。これを自動化しましょう。
KDEkwriteconfig5 というコマンドを使うことで、GUIの設定を変更できます。()
プロキシを有効にするコマンドは以下です。1になっている部分を0にすると無効にできます。

kwriteconfig5 --file kioslaverc --group 'Proxy Settings' --key ProxyType 1

これを大学のネットワークに接続したときだけ自動で実行するようにしましょう。 この場合はNetworkManager-dispatcher.serviceが便利です。
sudo systemctl enable --now NetworkManager-dispatcher.service でサービスを起動すると /etc/NetworkManager/dispatcher.d にあるスクリプトを状態変化時に実行してくれます。
ここに、GUIのプロキシを切り替えるスクリプトを設置しましょう。
以下のスクリプトでは大学のネットワーク判定をIPアドレスで行っています。弊学はローカルネットワークにグローバルIPが降ってくるのでこういうとき便利です。
他の判定方法としてはSSIDを確認する(nmcli -t -f name connection show --active)か、domainを見る(nmcli | grep domains | awk '$0=$2')というのが有ります。

#!/bin/zsh

log_tag='ProxyAutoToggle'

ip-sub(){
  default_dev="$(ip -4 route show default | awk '{print $5}' | head -1)"

  if [[ -z $default_dev ]]; then
    return 1
  fi

  ip -4 a show dev "${default_dev}" | grep -m1 'inet' | awk '{print $2}'
}

kde-proxy-toggle() {
  user="${1:? username}"
  mode="${2:? 0 or 1}"

  sudo --user="${user}" --group="${user}" kwriteconfig5 --file kioslaverc --group 'Proxy Settings' --key ProxyType "${mode}"
  sudo --user="${user}" --group="${user}" dbus-send --type=signal /KIO/Scheduler org.kde.KIO.Scheduler.reparseSlaveConfiguration string:''
}

case "$(ip-sub)" in
  133.80.*.*/*)
    logger 'proxy: enable school'

    for user in $(users | tr ' ' '\n' | sort --unique); do
      logger "user: ${user}"
      kde-proxy-toggle "${user}" 1
    done
    ;;
  *)
    logger 'proxy: disable'

    for user in $(users | tr ' ' '\n' | sort --unique); do
      kde-proxy-toggle "${user}" 0
    done
    ;;
esac

logger -p user.notice -t "${log_tag}" "configuration done."

CLI

CLIはhttp_proxyやhttps_proxyなどの環境変数を使ってプロキシの設定をします。
例えば以下のようにします。

export https_proxy="example.com:8080"

プロキシを無効にするには環境変数を消します。

unset https_proxy

さて、環境変数のセットとアンセットを自動化しましょう。
以下のスクリプトをzshrcに貼ってください。
proxy-onは引数にプロキシサーバーを渡すと必要な環境変数に値をセットしてくます。
proxy-offは反対に全てのプロキシ環境変数をアンセットします。
config-proxyはipアドレスでネットワークを判断してproxy-on、もしくはproxy-offを呼んでくれます。
つまり、config-proxyをコマンド実行直前に呼び出せれば良いわけです。
zshではpreexecというフックを使うことでコマンド実行前に関数を実行することができます。
最終行の add-zsh-hook preexec config_proxy がそうです。

proxy-on () {
  proxy="${1:? server:port}"

  export http_proxy="http://${proxy}"
  export HTTP_PROXY="${http_proxy}"
  export https_proxy="http://${proxy}"
  export HTTPS_PROXY="${https_proxy}"
  export ftp_proxy="${proxy}"
  export FTP_PROXY="${ftp_proxy}"
  export rsync_proxy="${proxy}"
  export RSYNC_PROXY="${rsync_proxy}"
  export all_proxy="${proxy}"
  export ALL_PROXY="${all_proxy}"
  export no_proxy='localhost,127.0.0.1,localaddress,.localdomain.com'
  export NO_PROXY="${no_proxy}"
}

proxy-off () {
        unset http_proxy
        unset HTTP_PROXY
        unset https_proxy
        unset HTTPS_PROXY
        unset ftp_proxy
        unset FTP_PROXY
        unset rsync_proxy
        unset RSYNC_PROXY
        unset all_proxy
        unset ALL_PROXY
        unset no_proxy
        unset NO_PROXY
}

ip-sub(){
  default_dev="$(ip -4 route show default | awk '{print $5}' | head -1)"

  if [[ -z $default_dev ]]; then
    exit 1
  fi

  ip -4 a show dev "${default_dev}" | grep -m1 'inet' | awk '{print $2}'
}

config_proxy(){
  case "$(ip-sub)" in
    133.80.*.*/*)
      proxy-on "cache.ccs.kogakuin.ac.jp:8080"
      ;;
    *)
      proxy-off
      ;;
  esac
}


autoload -Uz add-zsh-hook
add-zsh-hook preexec config_proxy

SSH

さて、SSHはサーバーへのアクセス以外にも、GitHubへのアクセスでよく使いますね。
弊学ではsshポートが閉じているので、どうにかしたいと思っている人は多いと思います。 本当は解決方法を書こうと思っていたのですが、書いてる途中に「あれっ グレーじゃね?」と思ってしまい一旦保留することにしました。
ホワイト判定されるか、他のホワイトな方法が見つかり次第、追記します。

終わりに

さて、本日のこの記事でKogakuin Univ Advent Calendar 2018は終了です。
公開がギリギリになってしましすみません :pray: