読者です 読者をやめる 読者になる 読者になる

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にこれが追加される。

f:id:masato47744:20170422024306p:plain

そうすると、もともとあった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が保存されない