穿越 Firewall 的作法

先看到「SSH over HTTPS (trofi.github.io)」這篇,原文「SSH over HTTPS」講怎麼利用 HTTPS 加上 CONNECT 指令穿過去。

作者有先介紹背景,他需要在醫院待個幾天,而醫院有免費的 WiFi 可以上網,但限制很多,基本上 TCP 的部分只有 80/tcp 與 443/tcp 會通,另外他有行動網路可以用 (但應該不是吃到飽的?),可以當作在現場直接設定 bypass 機制的工具:

I planned to spend 1-2 days in the hospital and did not plan to use the laptop.But now I am stuck here for the past two weeks and would like to tinker on small stuff remotely. The hospital has free Wi-fi access.

The caveat is that hospital blocks most connection types. It allows you only to do HTTP (TCP port 80) and HTTPS (TCP port 443) connections for most hosts. DNS (UDP port 53) and DoT (TCP port 853) seem to work as well at least for well-known DNS providers.

But SSH (TCP port 22 or most other custom ports) is blocked completely.

I wondered how hard would it be to pass SSH through HTTP or HTTPS. I had a GSM fallback so I could reconfigure remote server and try various solutions.

作者的方法就是在 TLS/SSL connection 上面跑 SSH,以前幹過,但就如同 comment 裡面提到的,Cisco 的 AnyConnect (主要是用 open-source client 的 OpenConnect 以及 open-source server 的 ocserv) 比較彈性,而且 AnyConnect 的協定會自動嘗試 UDP-based 的 DTLS,傳輸效率會比 TCP-based 的協定好,另外在 iOS 上可以直接裝 app store 裡面 Cisco 官方的 client 來用。

但從作者的其他文章看起來應該也是熟門熟路了,會這樣做應該是手上有 HTTPS 的 apache server 可以設定來用。

另外作者雖然沒寫出來,但想法應該是有 SSH 就可以在 command line 透過 -D 生出 SOCKS 服務當 proxy 讓其他程式使用,常見的應用程式大多都支援。

應該就是臨時要在醫院裡面待個一兩天時的暫時性方案,如果常態會遇到的話應該是會架 ocserv 來繞...

Uptime Kuma:UptimeRobot 的 Open Source Clone

UptimeRobot 算是我自己還蠻喜歡用的監控服務,各種常見的類型都支援,像是 HTTP/HTTPS website 的監控,ICMP Ping 或是 TCP 的監控,另外也提供 SSL certificate 的監控。

前陣子找資料的時候找到 Uptime Kuma,這是香港的 Louis Lam 開發的 open source software,光看名字就懷疑是 UptimeRobot 的致敬版本,裝起來用過後就更確定...

差不多用了一個多月了,基本上功能還蠻完整的,我把他接到我自己的 Slack 以及 Pushover 上,就很方便的可以監控服務:

挑一個點:

ISP 偽造出合法的 SSL certificate,對放在德國的 xmpp.ru 進行 MITM 監聽

標題有點複雜,先講一下 http-01 認證,這是目前 Let's Encrypt 上最常被使用的認證方式,是透過 HTTP 協定完成認證,你只要能回答 http://www.example.com/.well-known/acme-challenge/XXX 的內容就能過。

一般來說,這個 HTTP 位置只有這台伺服器的 owner 才有辦法提供,也就能確保不是任何人都可以申請。

但因為這邊走的是 HTTP,對於 ISP 這種比較特別的身分來說,他可以從中架設 HTTP 的 MITM Proxy 做到這件事情。

而有了合法的 SSL certificate 之後,中間的 MITM Proxy 就不只能聽 HTTP 了,還可以聽 HTTPS 的內容 (甚至修改內容)。

這次發生的事情就是在德國的 LinodeHetzner 機房內的服務,俄羅斯最大的 XMPP 服務 xmpp.ru 被搞出這件事情 (XMPP 是一個開放協定,不熟的話可以想像成類似 Line 或是 Telegram 的服務,但 XMPP 是開放協定,可以用自己喜歡的軟體連上):「Encrypted traffic interception on Hetzner and Linode targeting the largest Russian XMPP (Jabber) messaging service」。

他們在 Hetzner 的伺服器上有發現 network offline 的訊號:

[Tue Jul 18 12:58:29 2023] igb 0000:04:00.0 enp4s0: igb: enp4s0 NIC Link is Down
[Tue Jul 18 12:58:48 2023] igb 0000:04:00.0 enp4s0: igb: enp4s0 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: RX/TX

而在這個 network offline 的時間不久後 Let's Encrypt 發出了 xmpp.ru 與 jabber.ru 的 SSL certificate (crt.sh 上可以查到,在 99976947049997621208):

18 July 2023 issuing time is about the same when Hetzner server has lost network link for several seconds.

這些徵兆符合改接到 MITM Proxy 上的行為。

這次的事情很大條,因為這些伺服器是在德國,不是在俄羅斯... 事情才剛開始被報導出來,後續得繼續追蹤,而且應該也會促成新的機制被引入?

Google Chrome 將在 115 版之後預設使用 HTTPS 連線

Google Chrome (Chromium) 宣布 115 版後將預設使用 HTTPS 連線:「Towards HTTPS by default」。

查了一下 115.0.5790.98 是 2023/07/18 就出的版本,現在才冒出這篇文章有點晚,但大概就是講一下幹了什麼事情?

We're currently experimenting with this change in Chrome version 115, working to standardize the behavior across the web, and plan to roll out the feature to everyone soon.

主要的差異是在於,即使你輸入或是點擊的連結是 http://,他還是會優先嘗試 HTTPS:

Chrome will automatically upgrade all http:// navigations to https://, even when you click on a link that explicitly declares http://.

只有在 http:// 連結遇到 upgrade 到 HTTPS 失敗時才會回頭用 HTTP:

This works very similarly to HSTS upgrading, but Chrome will detect when these upgrades fail (e.g. due to a site providing an invalid certificate or returning a HTTP 404), and will automatically fallback to http://.

而本來就用 https:// 的連線就完全不會碰 HTTP 了。

講到推動 HTTPS 這點,前陣子剛好也是 Snowden 揭露美國 PRISM (菱鏡計畫) 十年的日子,當年在揭露後也因此加速了各種加密技術的基礎建設,像是 Let's Encrypt,而這也使得 HTTPS 更加普及,也讓 Google Chrome 現在可以預設切 HTTPS。

Windows 3.1 下的 GPT client

前幾天在 Hacker News 上看到「Show HN: WinGPT – AI assistant for Windows 3.1 (dialup.net)」這篇,原始文章「WinGPT: AI Assistant for Windows 3.1」在介紹 Windows 3.1 下的 GPT client。

雖然反差很大 (一個 20 世紀的 GUI 環境配上最新科技),但從 Hacker News 的討論可以看到,最熱烈的是在 16-bit 環境下實作 TLS 1.3 連線,也就原文裡的這段,提到了他是原生支援 TLS 1.3:

WinGPT connects to the OpenAI API server natively with TLS 1.3, so it doesn't require a proxy on a modern machine to terminate TLS. To see how I did this and some of the challenges, take a look at Modern TLS on 16-bit Windows. (As you'll see on that page, this is not a secure implementation).

不過他不是從零開始解,而是基於 wolfSSL 的實作,因為 wolfSSL 有支援 16-bit compiler,就不需要從零開始:

WolfSSL stood out among the pack as it had explicit 16-bit compiler support while being fully-featured and well-supported.

這是讓人看到會「蛤?」的東西 XD

CloudFront 支援 HTTP/3

雖然 HTTP/3 還沒有進到 Standard Track,但看到 CloudFront 宣佈支援 HTTP/3 了:「New – HTTP/3 Support for Amazon CloudFront」。

只要在 CloudFront 的 console 上勾選起來就可以了:

看了看 RFC 9114: HTTP/3 文件裡的描述,client 可以試著建立 UDP 版本的 QUIC 連線,但要有機制在失敗時回去用 TCPHTTP/2 或是 HTTP/1.1

A client MAY attempt access to a resource with an "https" URI by resolving the host identifier to an IP address, establishing a QUIC connection to that address on the indicated port (including validation of the server certificate as described above), and sending an HTTP/3 request message targeting the URI to the server over that secured connection. Unless some other mechanism is used to select HTTP/3, the token "h3" is used in the Application-Layer Protocol Negotiation (ALPN; see [RFC7301]) extension during the TLS handshake.

Connectivity problems (e.g., blocking UDP) can result in a failure to establish a QUIC connection; clients SHOULD attempt to use TCP-based versions of HTTP in this case.

另外一條路是在 TCP 連線時透過 HTTP header 告訴瀏覽器升級:

An HTTP origin can advertise the availability of an equivalent HTTP/3 endpoint via the Alt-Svc HTTP response header field or the HTTP/2 ALTSVC frame ([ALTSVC]) using the "h3" ALPN token.

像是這樣:

Alt-Svc: h3=":50781"

然後 client 就可以跑上 HTTP/3:

On receipt of an Alt-Svc record indicating HTTP/3 support, a client MAY attempt to establish a QUIC connection to the indicated host and port; if this connection is successful, the client can send HTTP requests using the mapping described in this document.

另外在 FAQ 裡面有提到啟用 HTTP/3 是不另外計費的,就照著本來的 request 費用算:

Q. Is there a separate charge for enabling HTTP/3?

No, there is no separate charge for enabling HTTP/3 on Amazon CloudFront distributions. HTTP/3 requests will be charged at the request pricing rates as per your pricing plan.

先開起來玩看看...

Let's Encrypt 更新了 ToS

在「Let's Encrypt’s subscriber agreement changes on Sept 21 (letsencrypt.org)」這邊看到的,Let's Encrypt 有提供 diff 的內容,在「LE-SA-v1.2-v1.3-diff.docx」這邊,你也可以用 Google Docs Viewer 看:「LE-SA-v1.2-v1.3-diff.docx」。

看起來主要是用語上的改變 (可能是律師的建議?),除了 revoke 的章節外看起來沒什麼大變化。而 revoke 的章節部份增加了這兩段文字:

You warrant to ISRG and the public-at-large, and You agree, that before providing a reason for revoking Your Certificate, you will have reviewed the revocation guidelines found in the “Revoking Certificates” section of the Let’s Encrypt documentation available at https://letsencrypt.org/docs/ , and that you will provide Your corresponding revocation reason code with awareness of such guidelines.

You acknowledge and accept that ISRG may modify any revocation reason code provided by You if ISRG determines, in its sole discretion, that a different reason code for revocation is more appropriate or is required by industry standards.

不確定自動化的 client 需不需要重新再 accept 一次?

AWS 宣佈了 API 的 TLS 1.0/1.1 日落期

AWS 宣佈了 API 的 TLS 1.0/1.1 日落期:「TLS 1.2 to become the minimum TLS protocol level for all AWS API endpoints」。

公告裡提到是 2023/06/28:

This update means you will no longer be able to use TLS versions 1.0 and 1.1 with all AWS APIs in all AWS Regions by June 28, 2023.

TLS 1.0 目前還堪用的應該是 AES + CBC 類的 cipher,在正確實做 mitigation 下加減可以用:

對於像是 Java 6 環境這類很老舊的系統,如果真的無法升級的話,可以想到 workaround 的方法是透過 self-signed CA + TLS proxy 來幫忙把 TLS 1.0 的連線請求解開,重包成 TLS 1.2 的連線。

25Gbps 下 HTTPS 的效率

作者家裡拉了 25Gbps 的 Internet 後 (可以參考先前寫的「25Gbps 的家用 Internet」這篇),然後發現 Internet 上好像拉不動 25Gbps 的量,所以自己在家裡先測試了現在 HTTPS 的極限速度:「25 Gbit/s HTTP and HTTPS download speeds」。

Client 是 AMD 的 5600X,算是目前最新的世代;Server 則是 Intel 的 9900K,目前最新應該是 12 代;測試用 35GB 的檔案來測,然後使用 TCP BBR (這邊沒有特別講,目前 kernel 內建的還是 v1)。

在單條 HTTP 的情況下 curl + nginx 與 curl + caddy 都可以直接跑滿 (23.4Gbps),Gonet/http 會卡在 20Gbps 左右。

如果是多條 HTTP 的話都可以跑滿 23.4Gbps。

但到了 HTTPS 的情況下最快的是 Go + net/http,可以跑到 12Gbps;curl + nginx 剩下 8Gbps;接下來 curl + caddy 的部份只有 7.5Gbps,而 go + caddy 只有 7.2Gbps。

上到多條 HTTPS 的情況大家都可以跑滿 23.4Gbps,除了 go + caddy 只能跑到 21.6Gbps。

另外作者試著用 kTLS 把 TLS 的工作丟進 kernel,就不需要全部在 nginx 內處理,速度基本上沒有太大變化,主要是降低了 CPU loading:

In terms of download speeds, there is no difference with or without KTLS. But, enabling KTLS noticeably reduces CPU usage, from ≈10% to a steady 2%.

算是一個有趣的發現,如果目前的 HTTPS 想要在 25Gbps 上面單線直接跑滿,還需要再 tune 不少東西...

HTTPS Everywhere 將在明年一月 (2023/01) 停止運作

在「Set Up HTTPS by Default in Your Browser」這頁看到的東西:

Note: HTTPS Everywhere will sunset in January 2023.

我把他 submit 到 Hacker News 上:「HTTPS Everywhere will sunset in January 2023 (eff.org)」,裡面有一些有趣的討論,像是這跟 Google 硬幹 Manifest v2 也有關:

It doesn't seem to be mentioned by the EFF, but coincidentally, January 2023 is when Manifest v2 extensions stop working in Google Chrome: https://developer.chrome.com/blog/mv2-transition/

但查了一下,目前好像沒有好的技術標準可以確保第一次的 HTTPS request。馬上想的到的是透過 DNS 的方式指定,這樣就可以透過 DNSSEC 保護不被竄改,但看起來沒有這個標準...