मुझे कुबेरनेट्स के लिए एनजीआईएनएक्स इनग्रेड कंट्रोलर के डिफ़ॉल्ट बैकएंड के लिए HTTP -> एचटीटीपीएस से होने के लिए एक स्वचालित रीडायरेक्ट प्राप्त करने में समस्या हो रही है, जहां नियंत्रक एडब्ल्यूएस क्लासिक ईएलबी के पीछे है; क्या यह संभव है?

गाइड के अनुसार ऐसा लगता है कि डिफ़ॉल्ट रूप से, HSTS सक्षम है

HTTP सख्त परिवहन सुरक्षा
HTTP स्ट्रिक्ट ट्रांसपोर्ट सिक्योरिटी (HSTS) एक ऑप्ट-इन सुरक्षा एन्हांसमेंट है जिसे एक विशेष प्रतिक्रिया शीर्षलेख के उपयोग के माध्यम से निर्दिष्ट किया गया है। एक बार समर्थित ब्राउज़र को यह शीर्षलेख प्राप्त हो जाने पर ब्राउज़र किसी भी संचार को HTTP पर निर्दिष्ट डोमेन पर भेजे जाने से रोकेगा और इसके बजाय सभी संचार HTTPS पर भेजेगा।

HSTS डिफ़ॉल्ट रूप से सक्षम है।

और HTTP को पुनर्निर्देशित करना -> HTTPS सक्षम है

रीडायरेक्ट के माध्यम से सर्वर-साइड HTTPS प्रवर्तन
डिफ़ॉल्ट रूप से नियंत्रक HTTP क्लाइंट को HTTPS पोर्ट 443 पर 308 स्थायी रीडायरेक्ट प्रतिक्रिया का उपयोग करके पुनर्निर्देशित करता है यदि TLS उस प्रवेश के लिए सक्षम है।

हालांकि, जब मैं नीचे कॉन्फ़िगर किए गए नियंत्रक को तैनात करता हूं और http://<ELB>.elb.amazonaws.com पर नेविगेट करता हूं तो मुझे कोई प्रतिक्रिया नहीं मिल पाती है (कर्ल रिपोर्ट Empty reply from server)। इसके बजाय मैं जो होने की उम्मीद करूंगा, वह यह है कि मुझे 308 को https पर फिर 404 पर रीडायरेक्ट करना चाहिए।

यह प्रश्न समान है: http से https पर पुनर्निर्देशन Kubernetes Nginx Ingress Controller में कस्टम बैकएंड सेवा के लिए काम नहीं कर रहा है लेकिन उन्होंने इसे हल किया एक कस्टम बैकएंड को तैनात करना और टीएलएस का उपयोग करने के लिए प्रवेश संसाधन पर निर्दिष्ट करना। मैं एक कस्टम बैकएंड को तैनात करने से बचने की कोशिश कर रहा हूं और केवल डिफ़ॉल्ट का उपयोग करना चाहता हूं, इसलिए यह समाधान मेरे मामले में लागू नहीं है।

मैंने अपनी परिनियोजन फ़ाइलों को जिस्ट पर साझा किया है और उन्हें यहां कॉपी भी किया है:

apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx-sit
  labels:
    app.kubernetes.io/name: ingress-nginx-sit
    app.kubernetes.io/part-of: ingress-nginx-sit
spec:
  minReadySeconds: 2
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: '50%'
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx-sit
      app.kubernetes.io/part-of: ingress-nginx-sit
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ingress-nginx-sit
        app.kubernetes.io/part-of: ingress-nginx-sit
      annotations:
        prometheus.io/port: '10254'
        prometheus.io/scrape: 'true'
    spec:
      serviceAccountName: nginx-ingress-serviceaccount
      containers:
        - name: nginx-ingress-controller
          image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.23.0
          args:
            - /nginx-ingress-controller
            - --configmap=$(POD_NAMESPACE)/nginx-configuration
            - --annotations-prefix=nginx.ingress.kubernetes.io
            - --publish-service=$(POD_NAMESPACE)/ingress-nginx
            - --ingress-class=$(POD_NAMESPACE)
            - --election-id=leader
            - --watch-namespace=$(POD_NAMESPACE)
          securityContext:
            allowPrivilegeEscalation: true
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
            # www-data -> 33
            runAsUser: 33
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          ports:
          - name: http
            containerPort: 80
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10

---

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-configuration
  namespace: ingress-nginx-sit
  labels:
    app.kubernetes.io/name: ingress-nginx-sit
    app.kubernetes.io/part-of: ingress-nginx-sit
data:
  hsts: "true"
  ssl-redirect: "true"
  use-proxy-protocol: "false"
  use-forwarded-headers: "true"
  enable-access-log-for-default-backend: "true"
  enable-owasp-modsecurity-crs: "true"
  proxy-real-ip-cidr: "10.0.0.0/24,10.0.1.0/24" # restrict this to the IP addresses of ELB
kind: Service
apiVersion: v1
metadata:
  name: ingress-nginx
  namespace: ingress-nginx-sit
  labels:
    app.kubernetes.io/name: ingress-nginx-sit
    app.kubernetes.io/part-of: ingress-nginx-sit
  annotations:
    # replace with the correct value of the generated certificate in the AWS console
    service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "arn:aws:acm:<region>:<account>:certificate/<id>"
    # Specify the ssl policy to apply to the ELB
    service.beta.kubernetes.io/aws-load-balancer-ssl-negotiation-policy: "ELBSecurityPolicy-TLS-1-2-2017-01"
    # the backend instances are HTTP
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http"
    # Terminate ssl on https port
    service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "*"
    # Ensure the ELB idle timeout is less than nginx keep-alive timeout. By default,
    # NGINX keep-alive is set to 75s. If using WebSockets, the value will need to be
    # increased to '3600' to avoid any potential issues.
    service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "60"
    # Security group used for the load balancer.
    service.beta.kubernetes.io/aws-load-balancer-extra-security-groups: "sg-xxxxx"
spec:
  type: LoadBalancer
  selector:
    app.kubernetes.io/name: ingress-nginx-sit
    app.kubernetes.io/part-of: ingress-nginx-sit
  loadBalancerSourceRanges:
    # Restrict allowed source IP ranges
    - "192.168.1.1/16"
  ports:
    - name: http
      port: 80
      targetPort: http
      # The range of valid ports is 30000-32767
      nodePort: 30080
    - name: https
      port: 443
      targetPort: http
      # The range of valid ports is 30000-32767
      nodePort: 30443
2
FGreg 27 जून 2019, 00:28

1 उत्तर

सबसे बढ़िया उत्तर

मुझे लगता है कि मुझे परेशानी पता चल गया है।

किसी कारण से डिफ़ॉल्ट सर्वर ने force_ssl_redirect को यह निर्धारित करते समय गलत पर सेट किया है कि क्या उसे आने वाले अनुरोध को HTTPS पर पुनर्निर्देशित करना चाहिए:

cat /etc/nginx/nginx.conf नोटिस rewrite_by_lua_block भेजता है force_ssl_redirect = false

...
    ## start server _
    server {
        server_name _ ;

        listen 80 default_server reuseport backlog=511;

        set $proxy_upstream_name "-";
        set $pass_access_scheme $scheme;
        set $pass_server_port $server_port;
        set $best_http_host $http_host;
        set $pass_port $pass_server_port;

        listen 443  default_server reuseport backlog=511 ssl http2;

        # PEM sha: 601213c2dd57a30b689e1ccdfaa291bf9cc264c3
        ssl_certificate                         /etc/ingress-controller/ssl/default-fake-certificate.pem;
        ssl_certificate_key                     /etc/ingress-controller/ssl/default-fake-certificate.pem;

        ssl_certificate_by_lua_block {
            certificate.call()
        }

        location / {

            set $namespace      "";
            set $ingress_name   "";
            set $service_name   "";
            set $service_port   "0";
            set $location_path  "/";

            rewrite_by_lua_block {
                lua_ingress.rewrite({
                    force_ssl_redirect = false,
                    use_port_in_redirects = false,
                })
                balancer.rewrite()
                plugins.run()
            }
...

फिर, LUA कोड के लिए force_ssl_redirect और redirect_to_https() की आवश्यकता होती है

cat /etc/nginx/lua/lua_ingress.lua

...
  if location_config.force_ssl_redirect and redirect_to_https() then
    local uri = string_format("https://%s%s", redirect_host(), ngx.var.request_uri)

    if location_config.use_port_in_redirects then
      uri = string_format("https://%s:%s%s", redirect_host(), config.listen_ports.https, ngx.var.request_uri)
    end

    ngx_redirect(uri, config.http_redirect_code)
  end
...

मैं जो बता सकता हूं force_ssl_redirect सेटिंग केवल इनग्रेड रिसोर्स पर नियंत्रित एनोटेशन nginx.ingress.kubernetes.io/force-ssl-redirect: "true" के माध्यम से। चूंकि मेरे पास प्रवेश नियम सेटअप नहीं है (यह उन अनुरोधों के लिए डिफ़ॉल्ट सर्वर होना है जो किसी भी प्रवेश से मेल नहीं खाते), मेरे पास इस सेटिंग को बदलने का कोई तरीका नहीं है।

तो मैंने निर्धारित किया कि मुझे एक अलग पोर्ट पर अपना खुद का कस्टम सर्वर स्निपेट परिभाषित करना है जिसमें force_ssl_redirect सही पर सेट है और फिर सर्विस लोड बैलेंसर को डिफ़ॉल्ट के बजाय उस कस्टम सर्वर पर इंगित करें। विशेष रूप से:

ConfigMap में जोड़ा गया:

...
  http-snippet: |
    server {
      server_name _ ;
      listen 8080 default_server reuseport backlog=511;

      set $proxy_upstream_name "-";
      set $pass_access_scheme $scheme;
      set $pass_server_port $server_port;
      set $best_http_host $http_host;
      set $pass_port $pass_server_port;

      server_tokens off;
      location / {
        rewrite_by_lua_block {
            lua_ingress.rewrite({
                force_ssl_redirect = true,
                use_port_in_redirects = false,
            })
            balancer.rewrite()
            plugins.run()
        }
      }
      location /healthz {
        access_log off;
        return 200;
      }
    }
  server-snippet: |
    more_set_headers "Strict-Transport-Security: max-age=31536000; includeSubDomains; preload";

नोट मैंने HSTS को सही ढंग से सक्षम करने के लिए server-snippet को भी जोड़ा है। मुझे लगता है क्योंकि ईएलबी से एनजीआईएनएक्स का ट्रैफिक एचटीटीपी नहीं एचटीटीपीएस है, एचएसटीएस हेडर डिफ़ॉल्ट रूप से सही ढंग से नहीं जोड़े जा रहे थे।

DaemonSet में जोड़ा गया:

...
        ports:
          - name: http
            containerPort: 80
          - name: http-redirect
            containerPort: 8080
...

संशोधित Service:

...
    service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"
...
  ports:
    - name: http
      port: 80
      targetPort: http-redirect
      # The range of valid ports is 30000-32767
      nodePort: 30080
    - name: https
      port: 443
      targetPort: http
      # The range of valid ports is 30000-32767
      nodePort: 30443
...

और अब चीजें काम करती दिख रही हैं। मैंने the Gist को अपडेट किया है, इसलिए इसमें पूरा कॉन्फ़िगरेशन शामिल है जिसका मैं उपयोग कर रहा हूं।

2
FGreg 15 जुलाई 2019, 21:06