天天看點

阿裡雲服務網格ASM之擴充能力(1):在ASM中通過EnvoyFilter添加HTTP請求頭

本系列文章講講述阿裡雲服務網格ASM的一些擴充能力:

歡迎掃碼入群進一步交流:

阿裡雲服務網格ASM之擴充能力(1):在ASM中通過EnvoyFilter添加HTTP請求頭

背景資訊

安全的HTTP請求頭可以支援以非常簡單的方式提高Web應用程式的安全性。OWASP提供了最佳實踐指南和程式設計架構,描述了如何使用安全請求頭保護應用程式的安全,包括了如下的基準設定:

HTTP頭 預設安全 描述
Content-Security-Policy frame-ancestors none; 防止其他網站進行Clickjacking攻擊
X-XSS-Protection 1; mode=block 激活浏覽器的XSS過濾器(如果可用);檢測到XSS時阻止渲染
X-Content-Type-Options Nosniff 禁用浏覽器的内容類型嗅探
Referrer-Policy no-referrer 禁用自動發送引薦來源請求頭
X-Download-Options noopen 禁用舊版本IE中的自動打開下載下傳功能
X-DNS-Prefetch-Control off 對頁面上的外部連結禁用推測性DNS解析
Server envoy 由Istio的入口網關自動設定
X-Powered-by 去掉該值,以隐藏潛在易受攻擊的應用程式伺服器的名稱和版本
Feature-Policy

camera ‘none’;

microphone ‘none’;

geolocation ‘none’;

encrypted-media ‘none’;

payment ‘none’;

speaker ‘none’;

usb ‘none’;

控制可以在浏覽器中使用的功能和API

通過curl指令可以看到Bookinfo示例應用程式的HTTP請求頭資訊,如下所示:

curl -I http://{入口網關服務的IP位址}/productpage
HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
content-length: 5183
server: istio-envoy
date: Tue, 28 Jan 2020 08:15:21 GMT
x-envoy-upstream-service-time: 28           

可以看到預設情況下,示例應用程式的入口首頁請求并沒有包含上述安全相關的HTTP請求頭。

接下來,将會介紹如何在ASM中通過Istio EnvoyFilter添加安全的HTTP請求頭。

定義EnvoyFilter

  1. apply -f - <apiVersion: networking.istio.io/v1alpha3

    kind: EnvoyFilter

    metadata:

    name: security-by-default-header-filter

    spec:

    filters:

    • listenerMatch:
      listenerType: GATEWAY           
      filterType: HTTP

    filterName: envoy.lua

    filterConfig:

    inlineCode: |
      function envoy_on_response(response_handle)
        function hasFrameAncestors(rh)
          s = rh:headers():get("Content-Security-Policy");
          delimiter = ";";
          defined = false;
          for match in (s..delimiter):gmatch("(.-)"..delimiter) do
            match = match:gsub("%s+", "");
            if match:sub(1, 15)=="frame-ancestors" then
              return true;
            end
          end
          return false;
        end
        if not response_handle:headers():get("Content-Security-Policy") then
          csp = "frame-ancestors none;";
          response_handle:headers():add("Content-Security-Policy", csp);
        elseif response_handle:headers():get("Content-Security-Policy") then
          if not hasFrameAncestors(response_handle) then
            csp = response_handle:headers():get("Content-Security-Policy");
            csp = csp .. ";frame-ancestors none;";
            response_handle:headers():replace("Content-Security-Policy", csp);
          end
        end
        if not response_handle:headers():get("X-Frame-Options") then
          response_handle:headers():add("X-Frame-Options", "deny");
        end
        if not response_handle:headers():get("X-XSS-Protection") then
          response_handle:headers():add("X-XSS-Protection", "1; mode=block");
        end
        if not response_handle:headers():get("X-Content-Type-Options") then
          response_handle:headers():add("X-Content-Type-Options", "nosniff");
        end
        if not response_handle:headers():get("Referrer-Policy") then
          response_handle:headers():add("Referrer-Policy", "no-referrer");
        end
        if not response_handle:headers():get("X-Download-Options") then
          response_handle:headers():add("X-Download-Options", "noopen");
        end
        if not response_handle:headers():get("X-DNS-Prefetch-Control") then
          response_handle:headers():add("X-DNS-Prefetch-Control", "off");
        end
        if not response_handle:headers():get("Feature-Policy") then
          response_handle:headers():add("Feature-Policy",
                                        "camera 'none';"..
                                        "microphone 'none';"..
                                        "geolocation 'none';"..
                                        "encrypted-media 'none';"..
                                        "payment 'none';"..
                                        "speaker 'none';"..
                                        "usb 'none';");
        end
        if response_handle:headers():get("X-Powered-By") then
          response_handle:headers():remove("X-Powered-By");
        end
      end           
    EOF
  • 将看到以下輸出顯示過濾器已成功部署:
envoyfilter.networking.istio.io/security-by-default-header-filter created           

驗證HTTP請求頭

  • 通過curl指令确認添加了安全HTTP請求頭,執行如下:
curl -I http://{入口網關服務的IP位址}/productpage
HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
content-length: 4183
server: istio-envoy
date: Tue, 28 Jan 2020 09:07:01 GMT
x-envoy-upstream-service-time: 17
content-security-policy: frame-ancestors none;
x-frame-options: deny
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
referrer-policy: no-referrer
x-download-options: noopen
x-dns-prefetch-control: off
feature-policy: camera 'none';microphone 'none';geolocation 'none';encrypted-media 'none';payment 'none';speaker 'none';usb 'none';           
  • 可以看到示例應用程式的入口首頁請求已經包含了上述介紹過的安全相關的HTTP請求頭。

由此可見,在ASM中可以使用EnvoyFilter以非常簡單的方式添加HTTP請求頭。

繼續閱讀