Firefox 與 Chrome 處理 Intermediate CA 的不同方式

Fediverse 上看到「The recording of my "Browsers biggest TLS Mistake" lightning talk at #37C3」這個,這是出自 37C3 的 lightning talk,影片不長,只有五分鐘,可以在「Browsers biggest TLS mistake」這邊看到。

正常的 HTTPS server 會送出 Intermediate CA certificate 與自己的 TLS certificate:

當伺服器端沒有設定好,通常是只送出自己的 TLS certificate:

這種情況在 Firefox 裡有處理,軟體本身會預載所有的 Intermediate CA 避免這種問題 (當然會需要跟著軟體更新),這點在三年前有提到過:「Firefox 試著透過預載 Intermediate CA 降低連線錯誤發生的機率?」,也就是這張投影片提到的情況:

Chrome 則是去看目前的 cache 資料,找看看是不是在其他地方有看到適合的 Intermediate CA 可以接起來:

這好像可以解釋為什麼之前遇到類似的問題的時候,在 Chrome 上面會需要進 chrome:// 裡面清東西才能重製...

JavaScript 的分號,以及 ASI (Automatic Semicolon Insertion)

目前 community 的主流跟我理出來的期望不一樣... 所以記錄一下。

先提一下背景,在 JavaScript 程式語言裡面,在大多數的情境下是可以省略掉分號 (;) 的,也就是說這兩種寫法都是合法的 JavaScript 語法:

console.log('Hello, world.')
console.log('Hello, world.');

這是因為在 ECMA-262 裡面有 ASI (Automatic Semicolon Insertion) 的設計:「Automatic Semicolon Insertion」。

ASI 設計本身是好的,可以讓開發者少處理 ;,但偏偏 EMCA-262 又允許千變萬化的換行,於是就造成了各種奇怪的現象。

因此早期在 community 上都是推薦無條件加上分號,這可以避免各種奇怪的 bug 與 error,像是「Do you recommend using semicolons after every statement in JavaScript?」以及「Should I use semicolons in JavaScript?」這些問答。

大家會推薦加上分號主要的原因是因為,不加上分號遇到的 error 與 bug 不是那種你知道很雷,所以會主動查詢 & 避開的問題:

而是各種平常寫就會遇到的情況,最容易中獎的是第二組敘述是 ([ 開頭的,像是 ECMA-262 文件裡面提到的 case 就算常見了:

a = b + c
(d + e).print()

// 等價於:
a = b + c(d + e).print();

而且不因為註解受到影響:

// blahblah
a = b + c

// blahblah
(d + e).print()

// 還是等價於:
a = b + c(d + e).print();

另外一個常見的情況是我們會利用 anonymous function 包出一個 block,避免變數污染到外面:

// I want to do blahblahblah...
(() => {
  const a = '';
  // ...
})()

// I want to do another blahblahblah...
(() => {
  const a = '';
  // ...
})()

大多數的情況應該會 error,除非第一個 anonymous function 傳回一個 callable,而這種情況跑出來的結果就更慘了...

另外這種 case 也是常見的情況:

// ...
[1, 2, 3].forEach(...)

// ...
[4, 5, 6].forEach(...)

// 等價於:
[1, 2, 3].forEach(...)[4, 5, 6].forEach(...)

這邊省略分號最大的問題是你無法知道「自己這行需不需要加上分號」,因為註解可能很長有個 30 行,所以依照這些現況,比較好的方法應該是全部加上分號,保持一致性。

但這幾年所有的 frontend framework 都是推動拿掉分號,這可以從各家的文件看到,就搞不懂 community 是怎麼推導出來的... 在全部都拿掉分號的情況下,遇到上面的情況就得寫成不一致的 style:

// ...
[1, 2, 3].forEach(...);

// ...
[4, 5, 6].forEach(...)

查了目前可行的 workaround,大多都是透過 ESLint 類的工具來擋可能會出現 bug 的地方,也只能先這樣做了...

用 Astrometa DVB-T2 聽 FM 廣播

算是接續「用 Astrometa DVB-T2 收數位無線電視台 (DVB-T)」這篇的內容,上篇有提到在台灣可以收 DVB-T 的數位電視內容,另外也有提到裡面的 RTL2832U 可以收 FM 廣播。

RTL2832U 在 Linux 下面的 FM 介面不是 /dev/radio0 這種 Radio Interface,而是透過 SDR 的方式,會產生出 /dev/swradio0 操作。

所以可以用 rtl_fm 這個工具從 SDR source 轉成 PulseAudio 吃的格式,像是要聽 107.7MHz 的台北之音,可以用這樣的指令聽:

sudo rtl_fm -f 107700000 -s 441000 -r 44100 | aplay -r 44100 -f S16_LE

但這樣做會是 mono (單聲道),這點可以從「Stereo FM receiving with RTL-SDR and Gnuradio - part 1」這邊的這張圖了解發生了什麼事情:

最低的地方會是左右聲道混在一起的 L+R 的單聲道訊號,這個方式可以讓很早期不支援兩聲道 (立體聲) 的 FM 收音機還是可以正常收聽,也剛好是 rtl_fm 時用到的地方。

而接下來是 19kHz 表示支援立體聲的訊號,然後從 23~53kHZ 的地方是 L-R 的訊號,最後面是 RDS 資料。

所以要把這包東西轉成 L 與 R 不是單純抽兩段 source 出來就解決了,而是需要在頻域上運算。

接著就是找看看有沒有已經做完的工具可以從 SDR source 運算然後播放,就找到 LuaRadio 這個專案,依照他的要求安裝 dependency,然後就可以直接跑了:

./luaradio examples/rtlsdr_wbfm_stereo.lua 107700000

在「rtlsdr_wbfm_stereo.lua」這頁的說明可以看到整個 flow 拉了很多處理。

不過在我的桌機上面,他會跳出三個 gnuplot 的視窗一直搶 window focus,要終止的話得按住 Ctrl-C 不放,然後點 terminal 想辦法讓 terminal 收到 Ctrl-C 才能停掉,看起來應該是 bug...

從 code 裡面可以看到他會偵測是否有 DISPLAY 這個環境變數來決定要怎麼做,所以本來以為改掉 DISPLAY 就可以了:

DISPLAY= ./luaradio examples/rtlsdr_wbfm_stereo.lua 107700000

不過看起來會卡住,還是得直接把相關的 code 都註解掉才行。

anyway,從官方給的圖可以看到整個收到的頻譜,以及 L+R 與 L-R 的樣子,也可以看到 19kHz 那邊有根訊號表示這是兩聲道:

這樣至少是有軟體可以聽立體聲了...

用 Astrometa DVB-T2 收數位無線電視台 (DVB-T)

以前用的 USB 電視棒壞掉了,去網拍上找了一隻新的來用,翻了一下跟 LinuxTVWiki 上的 Astrometa DVB-T2 這頁的圖片一樣 (2014 版本的圖):

先講一下重點,如果你買到的 USB 電視棒跟我一樣,應該可以看到兩個 source 可以收 DVB-T,而這兩個 source 都可以測試看看,在我家裡測試 Sony CXD2837ER 的收訊明顯好很多:

另外順便一提無關緊要的事情,本來在查資料的時候以為是 2013 的古董版本,但研究了一會兒發現 2013 版的「DVBT2」字比較大,所以不是 2013 版的:

插入到 Ubuntu 的時候可以看到幾個有趣的東西:

[Sat Dec 30 11:59:49 2023] usb 1-6.3: DVB: registering adapter 0 frontend 0 (Realtek RTL2832 (DVB-T))...
[Sat Dec 30 11:59:49 2023] dvbdev: dvb_create_media_entity: media entity 'Realtek RTL2832 (DVB-T)' registered.
[Sat Dec 30 11:59:49 2023] usb 1-6.3: DVB: registering adapter 0 frontend 1 (Sony CXD2837ER DVB-T/T2/C demodulator)...
[Sat Dec 30 11:59:49 2023] dvbdev: dvb_create_media_entity: media entity 'Sony CXD2837ER DVB-T/T2/C demodulator' registered.

意外的發現有兩個支援 DVB-T 的晶片,首先是 Realtek RTL2832 有被抓到,然後被註冊到 /dev/dvb/adapter0/frontend0 這邊。

Realtek 官網上只翻到了 RTL2832U 的資料,裡面比較有趣的是支援了 ISDB-T,不過如果在日本的話還需要 B-CAS 才能解:

Includes ISDB-T(SBTVD-T) 1-Seg

另外 RTL2832U 也支援 FM:

Includes Radio Support (FM/DAB/DAB+)

而第二個的 Sony CXD2837ER 被註冊到 /dev/dvb/adapter0/frontend1 這邊,另外在 LinuxTVWiki 可以看到 CXD2837ER 只被用在了 2018 版本,而且在外觀的部分提到了「or same as 2014 or 2017 revision」,所以看起來手上的版本應該是 2018 版的,但是殼長得跟舊的一樣。

翻了 Sony CXD2837ER 的 datasheet,可以看到支援 DVB-{T2,T,C}:

The Sony CXD2837ER is a combined DVB-T2 (incl.T2-Lite), DVB-T and DVB-C demodulator

看起來是為了 DVB-T2 而放進來的?不過台灣目前還是用 DVB-T 就是了。

Anyway,目前用起來唯一的缺點是看電視的時候同時跑 dvb-fe-tool --femon -f 1 會造成畫面破格,這點要再看看怎麼解決,不過不是大問題...

Gentoo 宣佈支援 binary package

Hacker News 上看到「Gentoo goes Binary (gentoo.org)」這篇,原文在「Gentoo goes Binary!」這。

Gentooportage 知名,這點在維基百科條目開頭就有提出來:

Gentoo Linux (pronounced /ˈdʒɛntuː/ JEN-too[3]) is a Linux distribution built using the Portage package management system. Unlike a binary software distribution, the source code is compiled locally according to the user's preferences and is often optimized for the specific type of computer.

這算是 Gentoo 的特色,不過即使 Gentoo 超愛 source package,也還是支援 binary package 安裝,但以前只提供重點套件,這包括了像是 Linux kernel 以及 gcc 這種套件,總是要有這些東西才能開始編軟體。

而這次公告宣佈要全面支援 binary package 算是個大轉變:

To speed up working with slow hardware and for overall convenience, we’re now also offering binary packages for download and direct installation!

目前 binary package 的主力會在 amd64 與 arm64 平台,然後提到這會對 mirror site 有額外的空間需求:

For most architectures, this is limited to the core system and weekly updates - not so for amd64 and arm64 however. There we’ve got a stunning >20 GByte of packages on our mirrors, from LibreOffice to KDE Plasma and from Gnome to Docker. Gentoo stable, updated daily.

從文末的圖也可以看到「the amount of binary package data in GByte for each architecture」得資訊:

想得到的客群大概是兩種,第一類是對於想用 Gentoo 看看的人來說會更好入手,尤其是手上是 Raspberry Pi 這些 CPU 不快的 SBC 會方便不少...

另外一種是不太在意效能,但是對某些 package 來說有高度客製化需求的人,會希望自己編這些 package 的人,透過 portage 自己調整。

Ruby 3.3.0 的消息

也是有點奇特,年底的慣例長假反而釋出 Ruby 3.3.0:「Ruby 3.3.0 Released」。

整體看起來比較大的改變有兩組,一塊是 parser 相關的消息,包括了 GNU Bison 換成 Lrama,兩個都是 LALR parser,但後者是 Ruby 寫的。

另外一塊是 JIT 相關的消息,包括了 YJIT 的持續進步,以及 RJIT 的引入。

看起來有在用 Ruby 的大型站台都跳進去幫 YJIT 發展了,這邊應該是正循環,會有更多的 feedback 與實作進來改善 YJIT。

而 RJIT 看起來是個實驗性質的東西,目前只會在 x86-64 上生效,不知道目標會是什麼:

Introduced a pure-Ruby JIT compiler RJIT and replaced MJIT.

MariaDB 11.4.0 preview release?

現在應該是西方年底的假期期間,意外的看到 MariaDB 貼出 11.4.0 preview release 的消息 (當然也有可能是排程發表?):「MariaDB 11.4.0 preview release now available」。

MariaDB 在十月的時候宣佈停掉一些周邊的產品線,「聚焦」回資料庫本體的消息後 (參考「MariaDB 停掉 SkySQL 與 Xpand」),這兩個月累積出來的東西其實不算太多,以這次文章理列出來的來看,主要是以 replication 相關的功能為主。

另外翻了一下維基百科上的資料,MariaDB 最新的 LTS 是 10.11,支援到 2028 年二月。

目前 MariaDB 還是個很微妙的狀態,如果就 engine 來說,重新聚焦有機會拿出跟 InnoDB 可以抗衡的技術嗎?或是在 cluster 以及 sharding 拿出比較奇特的技術?

估算 YouTube 影片總量的方式

Hacker News Daily 上看到「How big is YouTube? (ethanzuckerman.com)」這篇,原文在「How Big is YouTube?」。

算是個老問題了,而且應該是統計學上比較簡單的方法。先列出作者最後的成果:「TubeStats」。

作者用的方法是觀察 YouTube 的 vid:

Here’s how this works: YouTube URLs look like this: https://www.youtube.com/ watch?v=vXPJVwwEmiM

可以分析出來 vid 包括了 64-bit 的資訊,這個資料型態對工程師來說,看起來就很像是 uniformly distributed:

That bit after “watch?v=” is an 11 digit string. The first ten digits can be a-z,A-Z,0-9 and _-. The last digit is special, and can only be one of 16 values. Turns out there are 2^64 possible YouTube addresses, an enormous number: 18.4 quintillion. There are lots of YouTube videos, but not that many. Let’s guess for a moment that there are 1 billion YouTube videos – if you picked URLs at random, you’d only get a valid address roughly once every 18.4 billion tries.

然後就是隨機去產生 vid 去掃,這個方法跟 drunk dialing 的行為很像,算是 random sampling 的方式:

We refer to this method as “drunk dialing”, as it’s basically as sophisticated as taking swigs from a bottle of bourbon and mashing digits on a telephone, hoping to find a human being to speak to. Jason found a couple of cheats that makes the method roughly 32,000 times as efficient, meaning our “phone call” connects lots more often. Kevin Zheng wrote a whole bunch of scripts to do the dialing, and over the course of several months, we collected more than 10,000 truly random YouTube videos.

另外在 2011 年就有提出來利用 autocomplete 機制去算:

By comparing our results to other ways of generating lists of YouTube videos, we can declare them “plausibly random” if they generate similar results. Fortunately, one method does – it was discovered by Jia Zhou et. al. in 2011, and it’s far more efficient than our naïve method. (You generate a five character string where one character is a dash – YouTube will autocomplete those URLs and spit out a matching video if one exists.) Kevin now polls YouTube using the “dash method” and uses the results to maintain our dashboard at Tubestats.

目前他們的預估大約是 13B 左右的影片,換算大約是用掉 33.63 bits 了 (233.6):

In our case, our drunk dials tried roughly 32k numbers at the same time, and we got a “hit” every 50,000 times or so. Our current estimate for the size of YouTube is 13.325 billion videos – we are now updating this number every few weeks at tubestats.org.

而這邊提到的 32768 * 50k 會中一次的部分,這邊的大約是 30.61 bits,這樣加起來是差不多 64 bits 沒錯。

不過要注意的是,他們沒有給出 interval,所以 13B 的上下可能是一倍左右的差距 (6.5B~26B 之類的),這邊的數字當作概念比較好...

穿越 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 來繞...

CloudFront 支援 4096-bit RSA 的 SSL/TLS certificate 了

CloudFront 總算支援 4096-bit 的 RSA SSL/TLS certificate 了:「Amazon CloudFront now supports 4096-bit RSA TLS certificates」。

翻了一下 AWS ACM,看起來是 2020 年以前就支援 4096-bit RSA SSL/TLS certificate 了,CloudFront 晚蠻多的...

另外查了一下目前的強度,NSA 給出 2048-bit RSA 對到 112-bit strength,而 3072-bit RSA 對到 128-bit strength;至於 4096-bit RSA,目前是估算大約在 140-bit strength,有點微妙的數字。

看起來主要應該是給 compliance 需求使用的,有些舊的 library 未必支援 ECC 類的演算法,還是得透過拉高 RSA key size 來增加安全性。