PHP-FPMに環境変数を渡す
centos+nginx+php-fpmで構築したサーバで外部プロキシ経由のインターネット接続設定時でのメモ。
apache+phpで構築したサーバでは「/etc/environment」を起動時に読み込み可能な為、環境変数設定が可能だが上記環境では正常に読み込まれない。
調査・対応を下記へ記載しておく。
- 以下構築要件
■ 改修前 $ vim www_root/index.php $context = stream_context_create(['http' => ['timeout' => 3]]); $content = file_get_contents('http://[DST_SRV]', false, $context); ↓ ■ 改修後 nginx?php-fpm?側で/etc/environmentの設定が読み込まれない為、下記設定したが環境変数が反映されない。。 ※nginx、php-fpmの各ホームディレクトリで~/.bash_profileを設置したが、こちらも反映されず。。 $ /etc/php-fpm.d/www.conf clear_env = noの行のコメントアウトをはずして再読み込みすると解消する。 @@ -367,7 +367,7 @@ ; Setting to "no" will make all environment variables available to PHP code ; via getenv(), $_ENV and $_SERVER. ; Default Value: yes -;clear_env = no +clear_env = no 上記設定で環境変数が反映されない為、confへ直接記載する。 $vim /etc/php-fpm.d/www.conf env[HTTP_PROXY] = gwproxy.mysrv.com:3128 $ vim www_root/index.php $proxy_context = array( "http" => array( "proxy" => "tcp://".$_SERVER['HTTP_PROXY'], 'request_fulluri' => true, 'timeout' => 3, ), ); $context = stream_context_create($proxy_context); $content = file_get_contents('http://[DST_SRV]', false, $context);
上記設定で外部プロキシ経由したインターネット接続が可能になります。
apache+php環境同様にアプリ側でproxyを意識せず、透過的に設定可能なら良いのですが。
⇒curl_init関数使用した環境では、「/etc/environment」環境辺変数指定でproxy経由接続可能。file_get_contents関数を使用した場合で発生する事象と判明。関数仕様に依存した現象。
clear_env = noの行のコメントアウトをはずして再読み込みすると解消する。
$vim /etc/php-fpm.d/www.conf clear_env = no
red)
Centos7でFirewalldを用いたポートフォワード設定
CentOS 7で採用されたFirewallでのポートフォワード設定を構築したのでメモしておく。
firewall-cmd –directよりfirewall-cmd –add-rich-ruleの方が個人的には分かりやすく感じたのでこちらで。
firewall-cmd --add-masquerade firewall-cmd --add-rich-rule="rule family="ipv4" source address="10.0.0.0/8" accept" firewall-cmd --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" forward-port port="80" protocol="tcp" to-port="3128"' ※firewall-cmd --directの場合、[firewall-cmd --direct --add-forward-port=port=80:proto=tcp:toport=3128] # firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: ens160 ens192 sources: services: dhcpv6-client ssh ports: protocols: masquerade: yes forward-ports: sourceports: icmp-blocks: rich rules: rule family="ipv4" source address="10.0.0.0/8" accept rule family="ipv4" source address="10.0.0.0/8" forward-port port="80" protocol="tcp" to-port="3128"
これは”–permanent“が無いので一時的な設定になります。
firewall-cmd –reloadを実行すれば解除できます。
ルールを削除する場合、sed -i -e "s/--add-forward-port --remove-forward-port/"
参考
Centos系でのMASQUERADE構築
Centos7
●マスカレードホストルータ
- firewallコマンドにてMASQUERADE設定
# firewall-cmd --direct --get-all-rules firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.0.0.0/8 -j MASQUERADE firewall-cmd --direct --add-rule ipv4 filter POSTROUTING 0 -t nat -s [src_server_gip] -j MASQUERADE firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 -o ens160 -j ACCEPT firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 -i ens192 -m state --state RELATED,ESTABLISHED -j ACCEPT
※ens160:GIP,ens192:LIP
※ルール削除する場合、sed -i -e "s/--add-rule --remove-rule/"
- フォワード許可設定
# vim /etc/sysctl.conf net.ipv4.ip_forward=1
- 設定確認
# sysctl -p net.ipv4.ip_forward=1
●適用&確認
# systemctl unmask firewalld # systemctl enable firewalld # systemctl start firewalld # systemctl status firewalld
●一時的設定と恒久的設定について
設定のコマンドを説明する前に一時的設定と恒久的設定について説明していきます。
一時的設定(–permanentオプション無し)
「firewall-cmd」コマンドで設定を行う際に、「–permanent」オプションを指定しなければその設定は一時的な設定となり、サーバや>「firewalld」のサービスを再起動すると設定が消えてしまいます。
恒久的設定(–permanentオプションあり)
サーバの再起動や「firewalld」サービスの再起動で設定が消えてしまわないようにするためには、「–permanent」オプションを使用して設> 定を行う必要があります。
その際、「–permanent」オプションを指定して設定を行った場合は、そのままでは「firewalld」に設定が反映されないため「fiewall-cmd –reload」で設定を反映させる必要があります。
●子クライアント
- デフォルトゲートウェイをMASQUERADEするサーバへ向ける
# route add default gw [MASQUERADE_server_ip] ※削除する場合 route del default gw [MASQUERADE_server_ip]
- ルーティングの永続化
- /etc/sysconfig/network-scripts/route-[インタフェース名]
- これに下記のようなルーティング情報を記載
- xxx.xxx.xxx.0/24 via [ゲートウェイのIP] [インタフェース名(例:eth0)]
# cat /etc/sysconfig/network-scripts/route-eth0 [dst_server_gip]/32 via [MASQUERADE_server_ip] eth0
- 特定Dstの場合、ルーティング追加にて個別設定可能
# route add -net [dst_server_gip] netmask 255.255.255.255 gw [MASQUERADE_server_ip] eth0
- 確認
# ip route show
Centos6
●マスカレードホストルータ
- iptablesコマンドにてMASQUERADE設定
# iptables -t nat -I PREROUTING -i eth0 -s 172.31.0.0/16 -p tcp --dport 80 -j DNAT --to-destination [MASQUERADE_server_ip:port]
※上記で正常に動作しない場合、下記書き方も検討
# iptables -t nat -A PREROUTING -i eth0 -s ! [src_server_ip] -p tcp --dport 80 -j DNAT --to [MASQUERADE_server_ip:port] # iptables -t nat -A POSTROUTING -o eth0 -s 172.31.0.0/16 -d [MASQUERADE_server_ip] -j SNAT --to [src_server_ip] # iptables -A FORWARD -s 172.31.0.0/16 -d [MASQUERADE_server_ip] -i eth0 -o eth0 -p tcp --dport [MASQUERADE_server_port] -j ACCEPT
参考
squidによる多段プロキシ
多段でプロキシを組む場合、つまずいたのでメモがてら残しておく。
以下の様なパターンでアクセスが発生する。
- PC => WWW
- PC => PROXY (外部Proxy)(認証有) => WWW
- PC => PROXY (イントラGW) => PROXY(外部Proxy)(認証有) => WWW
今回の目的
- 外部Proxyサーバを経由して、アクセスさせる事により外部連携時のIP申請を省略する。
- イントラGWを経由する事により、外部Proxyサーバの認証情報を一括管理する。
- 各PCで外部Proxyサーバの認証情報を保持したくない。⇒セキュリティーポリシー・メンテナンス低下
- 上記構成を実現する為、下記ネットワークを組む。
- 各PC(ルーティング設定) ⇒ イントラGW ⇒ 外部Proxy ⇒ 外部接続
設定関連
各クライアントPC
- OSのシステムファイルへイントラGWを指定
$ cat /etc/environment # プロキシ設定 ============================================== # 実際の環境変数の設定 export http_proxy="http://gwproxy.mysrv.com:3128" export https_proxy="http://gwproxy.mysrv.com:3128" # プロキシを利用しないアドレスの指定(必須) export no_proxy="127.0.0.1,localhost" export NO_PROXY="$no_proxy"
イントラGW
$ sudo vim /etc/squid/squid.conf acl localnet src 192.168.0.0/16 http_access allow localnet cache_peer proxy.srv.com parent 3128 0 proxy-only login=ID:PASS never_direct allow all never_direct allow CONNECT visible_hostname unknown forwarded_for off
- cache_peer [上位プロキシの IP アドレス] parent [上位プロキシの ポート番号] [icp ポート番号] no-query [login=id:PASS]
- proxy-only…ピアから取ってきたオブジェクトは、ローカルに保存しない
- never_direct allow all…全てのリクエストを上位プロキシに転送する
- never_direct allow CONNECT…社外ネットワークに接続する場合のSSL接続は、上位Proxyへパス(SSLはデフォルトで直接接続しようとする)
- visible_hostname unknown…ホスト名の非表示
- forwarded_for off…一応IP隠す。
挙動確認
- 各クライアントPCから下記コマンド発行
$ curl -v -H 'Cache-Control: no-cache' -L 'http://google.com/' // 443の場合 $ git clone https://[user]@stash.test.com/src/test.git mydir
ホワイトリスト・除外リスト
never_direct
インターネット接続、つまりここまでに定義されていないドメインへのアクセスは、最終的に暗黙の転送先へ転送されます。
プロキシを使用する範囲、つまり「Exampleドメイン以外」の直接取得を禁止します。
never_direct allow yahoo
never_direct allow !example
always_direct
Exampleドメインだけは明示的に直接取得を許可します。さもないとプロキシーへ投げます。
always_direct allow example
サンプル
acl all src 0.0.0.0/0.0.0.0 acl host1 src [GIP:xxx.xxx.xxx.xxx]/255.255.255.255 acl yahoo dstdomain .yahoo.ne.jp .yimg.jp acl google dstdomain .google.com .google.co.jp acl mydomain dstdomain .mydomain.com .mydomain.co.jp #always_direct allow host1 #always_direct allow yahoo #always_direct allow google always_direct allow !mydomain ←mydomainは親プロキシを経由。通常特定URL許可指定するが、今回は特定URLのみ親プロキシを経由する為 #always_direct allow all ←上記マッチしなかったもの、つまり「上記リストではないもの」は親プロキシを経由せず直接アクセス許可
# cat access.log 1495610456.780 126 10.131.0.206 TCP_MISS/200 103173 GET http://www.mydomain.com/ - FIRSTUP_PARENT/[親プロキシIP] text/html←親プロキシ経由 1495610490.536 204 10.131.0.206 TCP_MISS/200 46298 GET http://www.google.co.jp/? - HIER_DIRECT/[DST_IP] text/html←直接アクセス // 443の場合 1497595884.998 2082 127.0.0.1 TCP_TUNNEL/200 4728 CONNECT stash.test.com:443 - FIRSTUP_PARENT/[親プロキシIP] -
ref)
Squid→Squidへ の多段プロキシ - それマグで!
cache_peer
HTTP proxy越しにSSHする
イントラGW
$ sudo vim /etc/squid/squid.conf # ssh proxy acl SSH_ports port 2222 acl Safe_ports port 2222 # ssh http_access allow CONNECT SSH_ports
各クライアントPC
$ cat .ssh/config Host stash.test.com User user HostName stash.test.com Port 2222 IdentityFile ~/.ssh/test.key ProxyCommand connect -H gwproxy.mysrv.com:3128 %h %p $ chmod 600 .ssh/config $ vim .ssh/test.key -- 鍵内容をコピー --- $ chmod 600 .ssh/test.key // connectコマンドが「/bin/bash: line 0: exec: connect: not found」の場合 $ rpm -ivh http://mirror.fairway.ne.jp/dag/redhat/el6/en/x86_64/rpmforge/RPMS/rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm $ rpm -ivh http://mirror.fairway.ne.jp/dag/redhat/el7/en/x86_64/rpmforge/RPMS/rpmforge-release-0.5.3-1.el7.rf.x86_64.rpm $ yum install --enablerepo=rpmforge connect // sshプロトコルよりソース取得 $ git clone ssh://git@stash.test.com:2222/test/test.git mydir
# cat access.log 1497509393.078 1 127.0.0.1 TCP_TUNNEL/502 0 CONNECT stash.test.com:2222 - FIRSTUP_PARENT/[親プロキシIP] - ←親プロキシ経由(親プロキシ側で拒否されている) 1498460374.471 7051 10.131.0.217 TCP_TUNNEL/200 1700614 CONNECT stash.test.com:2222 - FIRSTUP_PARENT/[親プロキシIP] - ←親プロキシ経由(正常接続)
CentOSでCVSを使用する場合
proxy経由でcvsを使用する場合、cvs 1.12.7以降で対応されいる様だが
CentOS6の標準repoでは現時点(20170712)でv1.11.xしか提供されてない為、src⇒buildの必要有り。
※CentOS7系では対象ソース無し
$yum install rpm-build.x86_64 libtool zlib-devel krb5-devel pam-devel $mkdir -p /usr/src/redhat/{BUILD,RPMS,SOURCES,SPECS,SRPMS} $wget -P /usr/src/redhat/SRPMS http://ftp.tmapy.cz/tmapy-twist/centos/6Server/obsolete/SRPMS/cvs-1.12.13-2.el6.1.src.rpm $rpmbuild --rebuild /usr/src/redhat/SRPMS/cvs-1.12.13-2.el6.1.src.rpm $rpm -ivh /root/rpmbuild/RPMS/x86_64/cvs-1.12.13-2.el6.1.x86_64.rpm
- 挙動確認
cvs -d ":pserver;proxy=gwproxy.mysrv.com;proxyport=3128:[user]@[cvs_server]:[port]/usr/home/cvsroot" login
ref)
Ubuntu日本語フォーラム / [質問] cvs pserver proxy経由でのアクセスについて
----hosts.allowの内容---- ALL: 192.168.0.0/255.255.0.0 ALL: 127.0.0.1
- 対策 hosts.allowに設定追加。
sshd: ALL
PHPのcRUL関数を用いたProxy接続
PHPでの開発時、Proxy経由で外部連携等々でcRUL接続を行う場合のサンプルコードを以下に示す。
<?php $ch = curl_init(); $fp = fopen("/tmp/test.txt", "w"); // 通信内容を保存するためのテンポラリファイル $errfp = tmpfile(); $loginpassw = 'ID:PASS'; $proxy_ip = 'http://proxy.test.com'; $proxy_port = '3128'; $url = 'http://www.google.com'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_VERBOSE, 1); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // proxy接続を無効にする場合、以下ブロックをコメント curl_setopt($ch, CURLOPT_PROXYPORT, $proxy_port); curl_setopt($ch, CURLOPT_PROXYTYPE, 'HTTP'); curl_setopt($ch, CURLOPT_PROXY, $proxy_ip); curl_setopt($ch, CURLOPT_PROXYUSERPWD, $loginpassw); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_FRESH_CONNECT, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_STDERR, $errfp); curl_setopt($ch, CURLOPT_FAILONERROR, 1); // file output //curl_setopt($ch, CURLOPT_FILE, $fp); $ret = curl_exec($ch); print_r($ret); // 記録した通信内容を読み出す fseek($errfp, 0); while (($line = fgets($errfp)) !== FALSE) { $tmp .= $line . "<br />"; } // 通信状況を出力 echo $tmp; curl_close($ch); fclose($fp); ?>
参考
https://ameblo.jp/itboy/entry-11983530735.html
■wwwサーバのProfileとして読み込ませる事も可能
wwwサーバをapacheユーザーとして起動しいる場合
proxy-user = "ID:PASS" proxy = "http://proxy.test.com:3128"
- ②ファイル権限変更
- $ chown apache: /var/www/.curlrc
- ③apacheユーザーへスイッチ
- ④Proxy経由での挙動確認
- $ curl -v -H ‘Cache-Control: no-cache’ -L ‘http://www.google.com/’
■システム全体へ適用
OS構成ファイル/etc/environmentへ配置
- environmentファイル作成
- $ vim /etc/environment
# プロキシ設定 ============================================== # 実際の環境変数の設定 export http_proxy="http://ID:PASS@proxy.test.com:3128" export https_proxy="http://ID:PASS@proxy.test.com:3128" # 大文字バージョンしか認識しないプログラム用 export HTTP_PROXY="http://ID:PASS@proxy.test.com:3128" export HTTPS_PROXY="http://ID:PASS@proxy.test.com:3128" # プロキシを利用しないアドレスの指定(必須) export no_proxy="127.0.0.1,localhost" export NO_PROXY="$no_proxy"
上記により全てのユーザーで共通して使用可能。
■蛇足
curl の基本設定ファイルを作ることが出来る
~/.curlrc Default config file, see -K, --config for details.
.curlrc に書く書き方は -K で指定する config ファイルと同じ
- ①configファイル作成
- $ vim /etc/curlrc
- [/var/www/.curlrc]参照
- $ vim /etc/curlrc
- ②configファイル指定した挙動確認
- $ curl -v -K /etc/curlrc -L ‘http://www.google.com/’
ここら辺を良しなに作成する一括設定スクリプト
下記サイト参照
中国のインターネット通信状況
中国国内からのパフォーマンス比較サイト
- https://www.dotcom-tools.com/website-speed-test.aspx
- http://www.china-webby.com/%E4%B8%AD%E5%9B%BD%E5%90%84%E7%9C%81%E3%81%8B%E3%82%89%E3%81%AE%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%82%B9%E3%83%94%E3%83%BC%E3%83%89%E6%B8%AC%E5%AE%9A%E3%83%84%E3%83%BC%E3%83%AB/
- http://www.thnet.co.jp/speed/chinese/access.html
また別サイトの過去情報ですが、下記に調査結果を転載
<Yahoo・Googleへの上海からのアクセススピード> Yahoo・Googleへの上海からのアクセススピードを計測したところ(2/2 12:30時点)、Yahoo!JAPANのスピードは、8.3 KB/秒、Yahoo!中国雅> 虎(サーバー在中国)のスピードは、188.1 KB/秒という結果になっています。つまり、Yahoo!中国雅虎のアクセススピードは、Yahoo!JAPAN> のアクセススピードの22.6倍の速さとなっており、大きな差が生じています。
参考
`
www site performance
■スピード調査方法
- 1.以下をコピー
javascript:(function(){%20var%20d=document;%20var%20s=d.createElement('scr'+'ipt');%20s.charset='UTF-8';%20s.language='javascr'+'ipt';%20s.type='text/javascr'+'ipt';%20s.src='//web-tan.forum.impressrd.jp/tools/pagespeedtiming/pagesppedtiming.js?t='+(new%20Date()).getTime();%20d.getElementsByTagName('head')[0].appendChild(s);%20})();
- 2.アドレスバーの[☆](星)をクリック
- 3.[編集]ボタンをクリック
- 4.[URL]にカーソルを移動して中身を全部消してクリップボードの内容を貼り付ける
- 5.[名前]には「ページ速度チェック」とか適当に入れる
- 6.完了ボタンをクリックし保存
- 7.調査対象サイトをchromeで表示(アドレスバーに対象URLを貼り付ける)
- 例)対象URL
- http://sample.com/golang
- 8.6で保存したブックマークを表示する
- 9.解析結果が表示されるので保存する
- 9-1.キーボードのctrl+Aにて全選択
- 9-2.キーボードのctrl+Cにて全コピー
- 10.txtエディターに貼り付ける
- 11.貼り付け結果を調査称名で保存する
参考