# AWS ALB 黏性研究 ###### tags: `AWS` > 目前 AWS ALB 黏性無法作用,在此做個深入研究 - - - ## 目前 Zucast Audio 部分 Audio 的部份,兩台主機是幾乎同時進線,就算沒有黏性也可以正常播放,因為 duration 是幾乎相同的,但是我們查看 AWS CloudFront 的 Cache statistics 就能發現,其實中間我們 Errors 還滿多的。 ![](https://i.imgur.com/FYt8RCv.png) ## AWS 說明黏性問題 參考資料:[黏性工作階段](https://docs.aws.amazon.com/zh_tw/elasticloadbalancing/latest/application/load-balancer-target-groups.html#sticky-sessions) ![](https://i.imgur.com/V9fmOyI.png) 官方說明需要瀏覽器設定 `SameSite=None; Secure` 才能讓性發揮作用。 - - - ## Google 說明跨域問題 參考資料:[Google Chrome 對於 SameSite Cookie 的設定](https://help.salesforce.com/articleView?id=000351874&language=zh_TW&mode=1&type=1) ![](https://i.imgur.com/iKqB3FN.png) 主要是防範 CSRF 的攻擊,所以在 80 版本後的預設設定都改為 `SameSite=Lax`,而 80 版本前預設為 `SameSite=None; Secure`,不過他的解決方式是使用 https。 - - - ## AWS ALB with https 建立 https 需要憑證,先嘗試使用 CDN 的 https 看看是否有效果。 - - - ## AWS CloudFront with https ![](https://i.imgur.com/YeR0CGB.png) 測試頁 : https://dev-vlive.staging.zucast.com/aws/ ![](https://i.imgur.com/IXkieUL.png) ![](https://i.imgur.com/0OTvFfz.png) 一樣沒有效果。 ### 嘗試設定 SameSite 使用 php 設定: ```php= <?php setcookie('cross-site-cookie', 'AWSALB', ['samesite' => 'None', 'secure' => true]); setcookie('cross-site-cookie', 'AWSALBCORS', ['samesite' => 'None', 'secure' => true]); ?> ``` ![](https://i.imgur.com/x6BmB6h.png) 再來看看黏性是否有發揮作用 ? ![](https://i.imgur.com/6sQCSY6.png) ![](https://i.imgur.com/XUDSntR.png) 一樣沒有發揮作用。 - - - ## HAProxy Stick HAProxy 的 Cookie 黏性不用 `SameSite=None; Secure` 也可以有黏性。 ![](https://i.imgur.com/bCVyHB0.png) ![](https://i.imgur.com/SblDoBc.png) - - - ## Nginx + SameSite 嘗試在 Nginx 的 response header 中加入 `SameSite=None; secure`,看是否能有黏性。 ``` location ~* \.ts$ { expires 20s; add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header Set-Cookie ass=01; add_header Set-Cookie 'SameSite=None; secure'; } location ~* \.m3u8$ { expires 1s; add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header Set-Cookie ass=01; add_header Set-Cookie 'SameSite=None; secure'; } ``` ![](https://i.imgur.com/jA67qr0.png) ![](https://i.imgur.com/TA6t4ZS.png) 沒有效果。 ``` location ~* \.ts$ { expires 20s; add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header Set-Cookie ass=01; add_header Set-Cookie 'cross-site-cookie=AWSALB; SameSite=None; secure'; add_header Set-Cookie 'cross-site-cookie=AWSALBCORS; SameSite=None; secure'; } location ~* \.m3u8$ { expires 1s; add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header Set-Cookie ass=01; add_header Set-Cookie 'cross-site-cookie=AWSALB; SameSite=None; secure'; add_header Set-Cookie 'cross-site-cookie=AWSALBCORS; SameSite=None; secure'; } ``` ![](https://i.imgur.com/9Kmd6IL.png) ![](https://i.imgur.com/hQz1tGS.png) 沒有效果。 ``` location ~* \.ts$ { expires 20s; add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header Set-Cookie ass=01; proxy_cookie_path / "/; secure; SameSite=None"; } location ~* \.m3u8$ { expires 1s; add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header Set-Cookie ass=01; proxy_cookie_path / "/; secure; SameSite=None"; } ``` 參考資料 : https://www.cnblogs.com/yyfh/p/13532689.html ![](https://i.imgur.com/cfOiVOH.png) ![](https://i.imgur.com/wbN815z.png) ``` location / { proxy_cookie_path / "/; secure; SameSite=None"; } location ~* \.ts$ { expires 20s; add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header Set-Cookie ass=01; } location ~* \.m3u8$ { expires 1s; add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header Set-Cookie ass=01; } ``` ![](https://i.imgur.com/fLcuqDi.png) ![](https://i.imgur.com/Kv8VCxM.png) ``` location / { proxy_cookie_path ~^/(.+)$ "/$1; secure; SameSite=none"; } location ~* \.ts$ { expires 20s; add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header Set-Cookie ass=01; } location ~* \.m3u8$ { expires 1s; add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header Set-Cookie ass=01; } ``` ![](https://i.imgur.com/1GWOzHB.png) ![](https://i.imgur.com/ZrYzLC0.png) - - - ## 比較 videojs 和 VLC 差異 我們把 Nginx 的 access log 打開,並加入 cookie 來查看 VLC 和 videojs 的差異。 ``` http { log_format main '[$time_local] - $remote_addr:$remote_port - $remote_user - $upstream_addr $upstream_status $upstream_response_time - ' '"$request" $status $bytes_sent $request_time ' '"$http_referer" - "$http_user_agent" ' '"$http_cookie"'; access_log logs/item_access.log main; } ``` 從 VLC 播放時的 log: ``` [26/Nov/2020:06:25:03 +0000] - 172.31.16.83:51146 - - - - - - - "GET /live/ch01-TQzEJa/index.m3u8 HTTP/1.1" 206 854 0.000 "-" - "Amazon CloudFront" "AWSALB=rP1SBs+ZxqCOnpn3atDOuTeDcJNEH+cShG0eoJ/fe3L4nnkcf9d+WY9gVTTZYKo+A9Qd4tQo+89Lp5XHDgGGAJDiBZLf5mi3KWwusWPwV53gkKXdi1E6zJRZ9Zhu; AWSALBCORS=rP1SBs+ZxqCOnpn3atDOuTeDcJNEH+cShG0eoJ/fe3L4nnkcf9d+WY9gVTTZYKo+A9Qd4tQo+89Lp5XHDgGGAJDiBZLf5mi3KWwusWPwV53gkKXdi1E6zJRZ9Zhu" [26/Nov/2020:06:25:03 +0000] - 172.31.7.67:50462 - - - - - - - "GET /live/ch01-TQzEJa/index77.ts HTTP/1.1" 200 7161 0.000 "-" - "Amazon CloudFront" "AWSALB=L3DCYzbbvzGOiZeuw9tZvubFMJ/UOwlxadqcenQxudGnY28DG5pqX1EwjVuA9RvjOcpqpfsGXkimpGnT6BCq/E0lSrNLlCRpu6uc5cI0kofCoDIG5xBRNk2FIEqy; AWSALBCORS=L3DCYzbbvzGOiZeuw9tZvubFMJ/UOwlxadqcenQxudGnY28DG5pqX1EwjVuA9RvjOcpqpfsGXkimpGnT6BCq/E0lSrNLlCRpu6uc5cI0kofCoDIG5xBRNk2FIEqy" [26/Nov/2020:06:25:03 +0000] - 172.31.7.67:50462 - - - - - - - "GET /live/ch01-TQzEJa/index.m3u8 HTTP/1.1" 206 854 0.000 "-" - "Amazon CloudFront" "AWSALB=QbIEJrV6rlP3nWNPKPmD963lX3Dbhi04gX9tO5+iSrIVBgQlHUj3eHPbgpwlVzQq3Ul7Xa4/WQ0MIzSHGN2n24IsjbeEjmuYax3DG5vmg+oEBmI0b5rAIz9ZIkXr; AWSALBCORS=QbIEJrV6rlP3nWNPKPmD963lX3Dbhi04gX9tO5+iSrIVBgQlHUj3eHPbgpwlVzQq3Ul7Xa4/WQ0MIzSHGN2n24IsjbeEjmuYax3DG5vmg+oEBmI0b5rAIz9ZIkXr" ``` 從 videojs 播放時的 log: ``` [26/Nov/2020:06:16:34 +0000] - 172.31.7.67:50042 - - - - - - - "GET /live/ch01-TQzEJa/index.m3u8 HTTP/1.1" 200 857 0.000 "-" - "Amazon CloudFront" "-" [26/Nov/2020:06:16:36 +0000] - 172.31.7.67:50042 - - - - - - - "GET /live/JBK4UC5d/index.m3u8 HTTP/1.1" 404 294 0.000 "-" - "Amazon CloudFront" "-" [26/Nov/2020:06:16:37 +0000] - 172.31.7.67:50046 - - - - - - - "GET /live/ch01-TQzEJa/index1306.ts HTTP/1.1" 404 294 0.000 "-" - "Amazon CloudFront" "-" ``` 從 VLC 播放都會帶 AWSALB 跟 AWSALBCORS 的 cookie ,而 videojs 都沒有,所以我們研究如何讓 videojs 能回傳 cookie 或許能成功。 ### HAProxy 的 log ``` [26/Nov/2020:06:50:49 +0000] - 172.19.1.10:36792 - - - - - - - "GET /live/JBK4UC5d/index.m3u8 HTTP/1.1" 200 876 0.000 "http://localhost/" - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36" "-" [26/Nov/2020:06:50:49 +0000] - 172.19.1.10:36792 - - - - - - - "GET /live/JBK4UC5d/174.ts HTTP/1.1" 200 331028 0.000 "http://localhost/" - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36" "-" [26/Nov/2020:06:50:50 +0000] - 172.19.1.10:36792 - - - - - - - "GET /live/JBK4UC5d/index.m3u8 HTTP/1.1" 200 876 0.000 "http://localhost/" - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36" "-" ``` HAProxy 開啟黏性,但是沒有回傳 cookie 也能有黏性。 ### Nginx load balancer 的 log ``` [26/Nov/2020:06:50:04 +0000] - 172.19.0.3:55206 - - - - - - - "GET /live/JBK4UC5d/130.ts HTTP/1.0" 404 1129 0.000 "http://localhost/" - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36" "dtCookie=v_4_srv_6_sn_77DD1D41574AFE737D4CCFC0AE1E0B53_perc_100000_ol_0_mul_1" [26/Nov/2020:06:50:05 +0000] - 172.19.0.3:55214 - - - - - - - "GET /live/JBK4UC5d/131.ts HTTP/1.0" 404 1130 0.000 "http://localhost/" - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36" "dtCookie=v_4_srv_6_sn_E7196F0E7A2C00A023C5FF1294503A10_perc_100000_ol_0_mul_1" [26/Nov/2020:06:50:05 +0000] - 172.19.0.3:55224 - - - - - - - "GET /live/JBK4UC5d/131.ts HTTP/1.0" 404 1129 0.000 "http://localhost/" - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36" "dtCookie=v_4_srv_7_sn_DFAD825FAAFD12F3292C0B2330D7D008_perc_100000_ol_0_mul_1" ``` Nginx 沒有開啟黏性也會回傳 cookie,不過有回傳也沒有黏性。 - - - ## 解決方式 在 videojs 使用 withCredentials: ``` player = videojs("acom-player", { playsinline: true, controls: true, autoplay: true, preload: 'auto', liveui: true, isAudio: true, html5: { hls: { withCredentials: true, overrideNative: true } } }); ``` 此時 Nginx 的部分就需要指定 Access-Control-Allow-Origin: ``` location ~* \.ts$ { expires 20s; add_header 'Access-Control-Allow-Origin' $http_origin; add_header 'Access-Control-Allow-Credentials' 'true'; add_header Set-Cookie ass=02; } location ~* \.m3u8$ { expires 1s; add_header 'Access-Control-Allow-Origin' $http_origin; add_header 'Access-Control-Allow-Credentials' 'true'; add_header Set-Cookie ass=02; } ``` 這樣我們再查看 access log : ``` [26/Nov/2020:07:37:58 +0000] - 172.31.16.83:55154 - - - - - - - "GET /live/ch01-TQzEJa/index388.ts HTTP/1.1" 200 7572 0.000 "-" - "Amazon CloudFront" "AWSALB=zfMgTd8dLp3DLc/hUP5gDcZT7UFalFE+4oKxGiCtEdGQ4WHruxcE4S27/jItRYgkZY+0GKk9J4IsF9/8lBnYJCL7ZUgoBlK0eyxmpTGhWxVV9bJh3stm8nWrBbmc" [26/Nov/2020:07:37:58 +0000] - 172.31.7.67:54598 - - - - - - - "GET /live/ch01-TQzEJa/index389.ts HTTP/1.1" 200 7196 0.000 "-" - "Amazon CloudFront" "AWSALB=hfFZoLagDJXHvoAJM9doDGN/9boObgGSb1UNYnv39D8c4CJuHk3XoHuK4iDbokVdQxef8lUTffx4mfK80zkAUvROhbN2qHU27CpxYniA2xvV3pB4ym/IPq7Y9GxH" [26/Nov/2020:07:37:58 +0000] - 172.31.7.67:54598 - - - - - - - "GET /live/ch01-TQzEJa/index390.ts HTTP/1.1" 200 7572 0.000 "-" - "Amazon CloudFront" "AWSALB=jNdQtvWc8Vp0xss5G8ZwNCpKcONfc5H0o5V0M0lcAmcR57j461+Jr74ZUh8623p5wtc0iUdk5l9VIrKYuRipjlC+IKqhtQS6h1hBDqGtuRgKtwhbTdToxDRa9EHE" ``` 再看看前端的 response header: ![](https://i.imgur.com/XLI9mLx.png) ![](https://i.imgur.com/UgatDFR.png) 成功了 :+1: - - - ## 結論 主要還是 CORS 規範比較嚴謹,一開始我們做 videojs 並沒有設置 `withCredentials`,所以 videojs 並不會回傳 Cookie,但當我們要回傳 Cookie 時,在 Nginx 端就需要設置 `Access-Control-Allow-Credentials=true` ,當 `Access-Control-Allow-Credentials=true` 時就不能把 `Access-Control-Allow-Origin` 設為 `'*'`,這樣就不符合規範,所以我們只能給定一個 domain,或是使用 `$http_origin` 讓所有 domain 都可以使用。 ### 目前 staging 的設定: 1. 在 dev-vlive.staging.zucast.com 跨域存取 live.staging.zucast.com 可以成功回傳 cookie。 2. 在 dev-vlive.staging.zucast.com 跨域存取 staging-alb-802874310.ap-southeast-1.elb.amazonaws.com 無法回傳 cookie。 ***※ 網站需要使用相似的 domain 才能真正將 cookie 回傳到 server。*** 參考資料: https://developer.mozilla.org/zh-TW/docs/Web/HTTP/CORS https://kknews.cc/zh-tw/code/romkr54.html