Deis/routerでwhitelistでIP制限する方法
Security Considerations - Deis Workflow Documentationで公式にIP制限する方法が紹介されてるが、403が出る。
なんで403になっちゃうのかをここを調べてみた。
公式通りにやっても403
公式ページにもあっさりこうすればできると書いてあるが、確かに403になってしまう。
$ kubectl --namespace=deis annotate deployments/deis-router router.deis.io/nginx.enforceWhitelists=true $ kubectl --namespace=deis annotate deployments/deis-router router.deis.io/nginx.defaultWhitelist="0.0.0.0/0"
deis/routerが生成するnginx.conf
deis/routerくんはただのnginxなので、生成されたnginx.confを見てみる。
・・中略 server { listen 8080; server_name deis.35.189.144.204.nip.io; server_name_in_redirect off; port_in_redirect off; set $app_name "deis/deis-controller"; allow 1.2.3.4; deny all; vhost_traffic_status_filter_by_set_key deis/deis-controller application::*; location / { proxy_buffering off; proxy_buffer_size 4k; proxy_buffers 8 4k; proxy_busy_buffers_size 8k; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $access_scheme; proxy_set_header X-Forwarded-Port $forwarded_port; proxy_redirect off; proxy_connect_timeout 10; proxy_send_timeout 1200; proxy_read_timeout 1200; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_pass http://10.3.243.160:80; } } ・・・略
単に、virtual hostでallow 1.2.3.4;
してるだけ。
アクセスログを見てみると、clientのIPがこちらのIPになってない。ここが問題のようだ。
2017/04/03 10:40:27 [error] 81#0: *739 access forbidden by rule, client: 10.146.0.2, server: deis.35.189.144.204.nip.io, request: "GET /v2/ HTTP/1.1", host: "deis.35.189.144.204.nip.io" [2017-04-03T10:40:27+00:00] - deis/deis-controller - 10.146.0.2 - - - 403 - "GET /v2/ HTTP/1.1" - 406 - "-" - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36" - "deis.35.189.144.204.nip.io" - - - deis.35.189.144.204.nip.io - - - 0.000
Client IPを保存するには??
kubenetes v1.5から、beta機能として、loadbalancerがclient IPをpreserveするような機能がついたので、その設定をいけば、client ipがrealなものになる。 やり方は、
$ kd annotate services/deis-router service.beta.kubernetes.io/external-traffic="OnlyLocal"
403になる原因としては、client ipがLoadbalancerのものか、kubernetesの何かのものになってしまったため。Deisの問題でもなく、GCPの問題でもなく、kubernetesの問題だった。以前からissueにあがっており、1.5からGCPとAzureのみ対応できた模様。AWSのELBに関しては、proxy protocolが使えるのであまり問題になっていなかった模様。
LoadbalancerにGCPのfirewall指定すればいいのでは?
この方法もkubernetesのannotateをすることで実施することができた。
単にfirewall設定をするだけでいけた。
https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/ をみると、loadBalancerSourceRanges
で設定できるとある。
When using a Service with spec.type: LoadBalancer, you can specify the IP ranges that are allowed to access the load balancer by using spec.loadBalancerSourceRanges.
annotateで指定してあげると、即座にfirewallにsource rangeが反映される。
$ kd annotate services/deis-router service.beta.kubernetes.io/load-balancer-source-ranges="5.6.7.8/32"
これを打つと、annotationsにこれが追加される。
そうすると、もともとあったfirewall ruleが更新される。
試しに、この状態で、service.beta.kubernetes.io/external-traffic=“OnlyLocal"を削除したら、接続できなくなった。 これがないとどちらにしろ、LBでfirewallを指定しても、deis-routerのnginxでIP制限したとしてもIP制限は働かないということになる。
まとめ
- GKE上のDeisでIP制限するにはGCPのfirewallを使うか、deis/routerのnginxでIP制限するかの2通りのやり方がある
service.beta.kubernetes.io/external-traffic="OnlyLocal
これがないとClientIPが保存されない