社内Proxyに阻まれていろいろ捗らない人のためのTips

#はじめに
タイトルの通り、社内Proxyがあるために、yumとかgit cloneができない人のためのTipsです。
Proxyに関する前提条件は以下の通りです。
> 1. 社内Proxyがある。
2. ProxyはID/Passの認証がある
3. FQDNによって制限されているページがある。(Blacklist方式)
4. Proxyに直接アクセスできないネットワークにある。（間接的にはアクセスできる）

またOSは主にLinux(CentOS,Ubuntu)ですが、Windows+Cygwinの話もたまにします。

ProxyのServerとPortは、__proxysrv:port__。ProxyのIDは__id__、Passは__pass__と表現します。
適宜読み替えてください。

###注意事項
全て<font color=red>自己責任</font>でお願いします。
理由(だいたいの場合がセキュリティ)があって、会社はこのような制限を設けています。
またこれの手っ取り早い解決方法は、スマホのテザリングを使ってProxyを経由しないことです。
ですが、この記事ではProxyを経由することに意味を見出しています。

#LinuxでProxy認証を突破する。
Linuxで.bashrcにこの設定を入れておけばだいたいOKです。

```Bash:.bashrc
export HTTP_PROXY_USER=id
export HTTP_PROXY_PASS=pass
export HTTP_PROXY=http://${HTTP_PROXY_USER}:${HTTP_PROXY_PASS}@proxysrv:port/
export HTTPS_PROXY=${HTTP_PROXY}
```
IDとPassはあとで使うので、それぞれ変数に入れておきます。
自分の環境だと`http_proxy`と`https_proxy`(小文字)も設定されている。。

あとは個別に設定する方法を記載します。

#GitにProxy設定を加える
```Bash:.bashrc
git config --global http.proxy ${HTTP_PROXY}
git config --global https.proxy ${HTTPS_PROXY}
git config --global url."https://".insteadOf git://
```
最後の行で`git://`も`https://`に変換してくれる。
もしくは、

```Bash:.gitconfig
[http]
        proxy = http://id:pass@proxysrv:port/
[https]
        proxy = http://id:pass@proxysrv:port/
[url "https://"]
        insteadOf = git://
```
でOK。（確か`.gitconfig`の中では環境変数は使えなかったと思う。）

#yumにProxy設定を加える。
※yumはHTTP_PROXYを読み込んでくれてる。

```Bash:/etc/yum.conf
proxy=http://proxysrv:port/
proxy_username=id
proxy_password=pass
```
`yum.conf`も環境変数は使えない。
`proxy=http://id:pass@proxysrv:port/`だけでもできる気がする。できないかな？

#apt-getにProxy設定を加える。(2017/04/27追記)
※apt-getもHTTP_PROXYを読み込んでくれます。
普段あまりubuntuを使わないのでスルーしてましたが、使う必要が出てきたので追記しておきます。

```bash:/etc/apt/apt.conf
Acquire::http::proxy "http://id:pass@proxysrv:port/";
Acquire::https::proxy "https://id:pass@proxysrv:port/";
```

#dockerにProxy設定を加える

```Bash:/etc/systemd/system/multi-user.target.wants/docker.service
[Service]
Environment="HTTP_PROXY=http://id:pass@proxysrv:port/" 
```
※他のページ見ると`system`直下にあるみたいだけど、自分の環境だと`multi-user.target.wants`配下にあった。

設定を加えたあとは、`daemon-reload`とサービスの再起動が必要。

```Bash
systemctl daemon-reload
systemctl restart docker
```

#pipにProxy設定を加える
※pipはHTTP_PROXYを読み込んでくれてる。

```Bash:~/.pip/pip.conf
[global]
proxy = id:pass@proxysrv:port
```

#wgetにProxy設定を加える
※wgetはHTTP_PROXYを読み込んでくれてる。

```Bash:/etc/wgetrc
https_proxy = http://id:pass@proxysrv:port/
http_proxy = http://id:pass@proxysrv:port/
ftp_proxy = http://id:pass@proxysrv:port/
```

##ちょっと休憩
上記の設定でだいたい捗るようになりました。
前提条件の1と2はクリアできたと思います。

ただ、実は自分のLinux環境は前提条件の4にあるため、
上記の設定でちゃんとproxy認証がクリアできるのか試せてないものもあります。。。
スイマセン。。

#許可されていないFQDNにアクセスする
前提条件の3ですね。ざっくりいうと以下のような構成を作ります。

> 自分のPC -> 会社Proxy -> インターネット -> 外部Proxy -> 目的のサイト

###外部Proxy
外部Proxyは自分で建てます。（たぶん建てたほうがセキュリティ的に良いし、この方法は自分の管理下じゃないとできないと思います。）
外部ProxyはAWSにLinuxのインスタンスを作って、squidを起動しておきます。
特別な設定をした覚えはありませんが、localのみ転送するようにしておきます。

```Bash:/etc/squid/squid.conf
http_port 127.0.0.1:8888 #ポートは自由に決めてください。
```

外部Proxyのサーバ名は**exproxy**とします。

###PCの準備
この方法ではsshを使います。PCのOSがWindowsだったので、別の用途で入れていたcygwinのsshを使います。
(PuttyやWin版のOpenSSHでもできると思います。)

何をするかというと、HTTP通信の上にSSHトンネルを作って、さらにsquidを通って目的のサイトにアクセスします。
**access on SSH tunnel on HTTP Proxy**という感じです。

まず初めにproxytunnelをインストールします。
http://proxytunnel.sourceforge.net/
ここにあります。(使い始めたのがずいぶん前なので詳細は忘れた・・・）

BashとSSHの設定を以下のようにします。

```Bash:.bashrc
export PROXYID=`echo $HTTP_PROXY_USER:$HTTP_PROXY_PASS | tr -d '\n' | base64`
```
Proxy認証のIDとPassをbase64でエンコードしています。

```Bash:~/.ssh/config
Host exproxy
        HostName        exproxy # AWSインスタンスのIPアドレス
        Port    22
        User    ubuntu
        IdentityFile    ~/.ssh/exporxy.pem # AWSインスタンス接続用の認証ファイル
        ServerAliveInterval     60
        ExitOnForwardFailure    yes
        LocalForward    9999 localhost:8888 # PCの9999ポートを外部Proxyの8888に転送します。
        GatewayPorts    yes
        ProxyCommand /usr/local/bin/proxytunnel -p proxysrv:port -H "Proxy-Authorization: Basic ${PROXYID}" -d exproxy:22
```

これで準備が整いました。`ssh -fN exproxy`でコネクションを確立して、
ブラウザのproxyを`localhost:9999`にしてください。
`nohup ssh -fN exproxy &`と実行すればターミナルは閉じても構いません。

###何が起こっているか、簡単に解説。
PCからサイトAにアクセスすると全体の経路は、
>PC -> 社内Proxy -> 外部Proxy -> サイトA

のようになります。これを分解します。

>PC -> 社内Proxy -> 外部Proxy:22

社内Proxyから見ると、外部Proxy(exproxy)の22に対してHTTP通信しているように見えています。`http://exporxy:22/`みたいな感じですかね。
そして一見サイトAにアクセスしようとしているようには見えません。
（ちゃんと見ればわかるかもしれません。）
や、SSHだから暗号化されてるのか。だから見てもわからないかも。(2017/04/14加筆)

>社内Proxy(SSH) -> 外部Proxy:22 -> 外部Proxy:8888(HTTP/HTTPS) -> サイトA

外部Proxyから見ると、社内ProxyからSSHされているように見え、
更にlocalhostからsquid(8888)を経由してどこかのサイトにアクセスしているように見えます。
最終目的地のサイトAからは外部Proxyからのアクセスに見えます。

たぶん社内Proxyのログを見ると、外部Proxyに対するコネクションが長時間つながっていて、さらにデータ量も普通のHTTP通信より多いことがわかると思います。
・・・なのでしっかり情報システム部がモニタリングしているとすぐバレます。

あとAWSの転送量による料金が気になるところではありますが、
それは使い方にもよりますが、あんまり大したこと無さそうです。
自分は無料枠も含めて10Gb/月くらいで、$0.40くらいしかかかっていません。

ssh -D(動的フォワード)でもできるんですが、SOCKSプロキシで動かないアプリケーションもあります。
なので静的ポートフォワーディングでやってます。
また静的ポートフォワーディングだけだと外部Proxyの向こう側のサイトを固定しなければならないので、
外部ProxyにSquid(http proxy)を建てて、その先も自由に行けるようにしています。
(で、説明あってるかな・・・？)
動的フォワードを使う場合は、configの`LocalForward`の箇所を
`DynamicForward  9999`に変えればできるはず。
またその時は外部Proxy側でSquidは不要になります。
(2017/04/14加筆)

#内部ネットワークからインターネットにアクセスする
上記の方法の応用です。前提条件としては内部ネットワークにあるLinuxから自分のPCにアクセスできることがあります。
> Linux@内部ネット -> 自分のPC

やり方は簡単で、LinuxのProxy設定を全て`PC:9999`にするだけです。
IDとPassは要りません。Proxy認証はSSHで外部Proxyに接続するときに行っています。

> Linux@内部ネット -> 自分のPC -> 社内Proxy -> 外部Proxy -> サイトA

これで内部ネットにあるLinuxから外部サイトにアクセスできるようになりました。

# さいごに
最後にもう一度言いますが<font color=red>自己責任</font>でお願いします。
情報システム部なんかに目を付けられるかもしれませんし、
なんらかのセキュリティホールになり得ます。
その辺をご理解の上、自己責任、自己判断で行ってください。

# ご参考
似たようなことを考える人は大勢いるようで。ここにないものは↓で補足できますのでご参考に。
proxy環境下の設定（ubuntu 14.04)
http://qiita.com/showsuzu/items/9ee031208d38ff8ac889