LoginSignup
4
3

More than 5 years have passed since last update.

mod_myfixip を試してみた

Last updated at Posted at 2015-04-17

Proxy Protocol とは

http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt にある、proxy の後ろにいる子達に client の IP address を教えてあげる為の protocol。HTTP のときに X-Forwarded-For header を足したりするのとは違って、L4 の payload の頭に IP address をぶっこむイメージ。なので後ろにいる子達がぶっこまれた IP address を解釈できないといけない。

Proxy Protocol 対応状況は?

http://blog.haproxy.com/haproxy/proxy-protocol/ が逐次更新されているみたい。Apache HTTP Server の module が紹介されている。

nginx はもうちょっと前から対応している、オフィシャルに。

ELB + Apache HTTP Server + mod_myfixip を試してみる

普通に ELB を使ってみる

ELB は TCP 80, TCP 80 で Listener を作りました。

backend instance には Amazon Linux を選択。

[ec2-user@ip-172-31-0-231 ~]$ sudo yum -y install httpd
[ec2-user@ip-172-31-0-231 ~]$ echo "ok" | sudo tee /var/www/html/index.html
[ec2-user@ip-172-31-0-231 ~]$ sudo service httpd start
[ec2-user@ip-172-31-0-231 ~]$ curl -v proxy-test-1912640500.us-west-2.elb.amazonaws.com
ok
* Closing connection 0

ELB で Proxy Protocol を有効化してみる

Proxy Protocol の有効化は http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/enable-proxy-protocol.html に書いてあります。Management Console は未対応のようでした。

[ec2-user@ip-172-31-0-209 ~]$ aws --region us-west-2 elb create-load-balancer-policy --load-balancer-name proxy-test --policy-name EnableProxyProtocol  --policy-type-name ProxyProtocolPolicyType --policy-attributes AttributeName=ProxyProtocol,AttributeValue=True
[ec2-user@ip-172-31-0-209 ~]$ aws --region us-west-2 elb create-load-balancer-policy --load-balancer-name proxy-test --policy-name EnableProxyProtocol  --policy-type-name ProxyProtocolPolicyType --policy-attributes AttributeName=ProxyProtocol,AttributeValue=True

1 つめで Policy を作って、2 つめで TCP 80 port にこれを適用です。確認してみるとちゃんと適用されているようです。

[ec2-user@ip-172-31-0-209 ~]$ aws --region us-west-2 elb describe-load-balancers --load-balancer-name proxy-test --query 'LoadBalancerDescriptions[0].BackendServerDescriptions'
[
    {
        "InstancePort": 80, 
        "PolicyNames": [
            "EnableProxyProtocol"
        ]
    }
]

curl でアクセスしてみるとちゃんとエラーが出るようになりました:

[ec2-user@ip-172-31-0-209 ~]$ curl http://proxy-test-1912640500.us-west-2.elb.amazonaws.com/
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
Request header field is missing ':' separator.<br />
<pre>
GET / HTTP/1.1</pre>
</p>
<hr>
<address>Apache/2.2.29 (Amazon) Server at ip-172-31-0-231.us-west-2.compute.internal Port 80</address>
</body></html>

backend instance 上で sudo tcpdump -X -nn tcp port 80 とすると、PROXY.TCP4 という文字列が見え client の IP address が伝わってるのが見えます

05:28:06.399141 IP 172.31.1.154.35083 > 172.31.0.231.80: Flags [P.], seq 1:46, ack 1, win 71, options [nop,nop,TS val 9366818 ecr 9352303], length 45
    0x0000:  4500 0061 f7f9 4000 4006 e7dd ac1f 019a  E..a..@.@.......
    0x0010:  ac1f 00e7 890b 0050 e8da 1ad6 8442 e13e  .......P.....B.>
    0x0020:  8018 0047 d5ce 0000 0101 080a 008e ed22  ...G..........."
    0x0030:  008e b46f 5052 4f58 5920 5443 5034 2035  ...oPROXY.TCP4.5

Health Check 自体はこの段階では成功しています。Proxy してないし Proxy Protocol 使わないからですね、きっと。

backend で Proxy Protocol を有効化

mod_myfixip の使い方は上記の source に書いてあるので素直に実行してみます。compile には httpd-devel と gcc があれば十分そうです。

[ec2-user@ip-172-31-0-231 ~]$ sudo yum install -y httpd-devel gcc
[ec2-user@ip-172-31-0-231 ~]$ wget https://raw.githubusercontent.com/ggrandes/apache22-modules/master/mod_myfixip.c
[ec2-user@ip-172-31-0-231 ~]$ sudo apxs -c -i mod_myfixip.c

config file も一先ず最低限の変更だけします。

[ec2-user@ip-172-31-0-231 ~]$ diff -u /etc/httpd/conf/httpd.conf.org /etc/httpd/conf/httpd.conf
--- /etc/httpd/conf/httpd.conf.org  2015-04-17 05:38:04.540734203 +0000
+++ /etc/httpd/conf/httpd.conf  2015-04-17 05:44:06.569742559 +0000
@@ -199,6 +199,7 @@
 LoadModule disk_cache_module modules/mod_disk_cache.so
 LoadModule cgi_module modules/mod_cgi.so
 LoadModule version_module modules/mod_version.so
+LoadModule myfixip_module modules/mod_myfixip.so

 #
 # The following modules are not loaded by default:
@@ -1008,3 +1009,8 @@
 #    ErrorLog logs/dummy-host.example.com-error_log
 #    CustomLog logs/dummy-host.example.com-access_log common
 #</VirtualHost>
+
+<IfModule mod_myfixip.c>
+  RewriteIPResetHeader off
+  RewriteIPAllow 172.31.0.0/16
+</IfModule>

これで httpd を再起動します。すると? client の global IP address が記録されるようになりました。

xxx.xxx.xxx.xxx - - [17/Apr/2015:06:05:24 +0000] "GET / HTTP/1.1" 200 3 "-" "curl/7.40.0"

問題・課題

ざっと source を見たかぎり、ELB node の IP address を取る方法が分かりませんでした。C 力が足りない...。

ぐぐったら https://github.com/roadrunner2/mod-proxy-protocol というのもありましたが試していません...。

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3