2022年11月10日 星期四

Spring Boot 啟用 mTLS

最近在幫專案導入 Spring Boot,導入時比較麻煩的地方,是要保持專案的權限控制,也就是要讓它依然能夠正常以 Mutual TLS 的方式進行驗證。雖然在這個狀況下,往好處想是我們已經有現成的測試程序,能夠用來驗證是否 Mutual TLS 有正常運作,不過當驗證異常的時候,要找出問題還是蠻費工夫的…。這篇會稍微紀錄一點相關的資訊。

什麼是 Mutual TLS?

Mutual TLS(或者簡稱 mTLS)是驗證範圍更寬一點的 HTTPS,一般討論 HTTPS 時,比較常見的討論對象是單向的 TLS,也就是讓客戶端驗證伺服器是否真的是它宣稱的伺服器。而 Mutual TLS 則是雙向的 TLS,不但客戶端要驗證伺服器、伺服器也要驗證客戶端。換句話說,伺服器和客戶端都需要有私鑰和憑證。

TLS 相關名詞解釋

TLS 在運作時,會需要有公鑰(public key)和私鑰(private key),這裡就不解釋各自的用途了。實際 TLS 在運作時,通常會以私鑰和憑證(certificate)的形式在表示,其中憑證的內容是包含了公鑰、發行者(Issuer)和有效時間等資訊的檔案。也就是說,憑證會拿來提供給對方做驗證。

在使用 curl 時,會注意到 curl 允許的 --key--cert 的格式是 PEM,這是因為 curl 就只支援 PEM 格式。不過在 Java 的世界中,比較麻煩的是 Java 一般不支援 PEM,所以網路上的文章常常會看到有使用 keytool 的流程,這個流程是為了把 PEM 格式的私鑰和憑證,轉換成 PKCS #12(.p12)或者 Java KeyStore 格式(.jks)的檔案。可以參考公鑰密碼學標準

除了 KeyStore 以外,另外還會有個 TrustStore 的玩意兒。兩個的功能剛好相反,KeyStore 是用來讓別人做驗證、TrustStore 的功能則是用來驗證別人。所以說,KeyStore 的產生會使用自己的私鑰和憑證,這是因為產生出來的 KeyStore 內容也會包含自己的憑證資訊。

設定 Spring Boot 的 SSL

具體設定方法,可以參考官方文件中 How-to 章節的 SSL 部份。不過我個人其實覺得官方文件寫得還挺籠統的…。

實際我自己在設定時,在 Spring Boot + Jetty 底下有遇到幾種奇怪的狀況:

  1. 使用 keystore(JKS) 和 truststore,然後 Spring Boot 顯示有正常啟動 HTTPS,但結果用 curl 或 openssl 檢查時,都檢查不到有 HTTPS。
  2. 使用 PEM,然後 HTTPS 正常啟動,憑證也能正常被客戶端讀取,但 mTLS 一直失敗。

最後這裡直接紀錄目前會成功的版本,是採用 PKCS12 的格式讓 Spring Boot 讀取。

server.port=8443
server.ssl.enabled=true
server.ssl.key-store=/path/to/key/store/my_keystore.p12  # PKCS12 檔案的路徑
server.ssl.key-alias=accio  # 別名,在產生 PKCS12 檔的時候指定的名字
server.ssl.key-store-password=mypassword  # PKCS12 的密碼
server.ssl.trust-store=/path/to/trust/store/my_truststore.jks  # trust store 檔案的路徑
server.ssl.trust-store-type=JCEKS  # trust store 檔案的格式
server.ssl.trust-store-password=mypassword  # trust store 的密碼
server.ssl.client-auth=want  # 啟用 mTLS,但不強制

如何檢查 HTTPS?

使用 curl 或者 openssl 都可以做檢查 HTTPS。

openssl

openssl 時,就是讓 openssl 模擬成 client,指令如下:

openssl s_client -connect localhost:8443

以我的狀況,如果 HTTPS 啟動但有問題 (?) 的話,會出現以下這樣的訊息。

[root@a976d6ac5637 ~]# openssl s_client -connect localhost:8443
CONNECTED(00000003)
140387372447632:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:769:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 289 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : 0000
    Session-ID:
    Session-ID-ctx:
    Master-Key:
    Key-Arg   : None
    Krb5 Principal: None
    PSK identity: None
    PSK identity hint: None
    Start Time: 1667406122
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---

訊息中可以明確看出,openssl 並沒有找到合適的 cipher 能夠進行加密連線。

而如果是正常的 HTTPS 的話,會像是這樣:

[root@a976d6ac5637 ~]# openssl s_client -connect google.com:443
CONNECTED(00000005)
depth=3 C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA
verify return:1
depth=2 C = US, O = Google Trust Services LLC, CN = GTS Root R1
verify return:1
depth=1 C = US, O = Google Trust Services LLC, CN = GTS CA 1C3
verify return:1
depth=0 CN = *.google.com
verify return:1
---
Certificate chain
 0 s:/CN=*.google.com
   i:/C=US/O=Google Trust Services LLC/CN=GTS CA 1C3
 1 s:/C=US/O=Google Trust Services LLC/CN=GTS CA 1C3
   i:/C=US/O=Google Trust Services LLC/CN=GTS Root R1
 2 s:/C=US/O=Google Trust Services LLC/CN=GTS Root R1
   i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
---
Server certificate
-----BEGIN CERTIFICATE-----
....(ignored)....
-----END CERTIFICATE-----
subject=/CN=*.google.com
issuer=/C=US/O=Google Trust Services LLC/CN=GTS CA 1C3
---
No client certificate CA names sent
Server Temp Key: ECDH, X25519, 253 bits
---
SSL handshake has read 7270 bytes and written 281 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-CHACHA20-POLY1305
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-CHACHA20-POLY1305
    Session-ID: D0F1CB0DAE17297143F933D8C93BB905D088849CAAFED06698803C8F14367771
    Session-ID-ctx:
    Master-Key: ADC789FEFEF3A3747E6741D23B090CAA3E1BBEB8B6DED6EB44910E45257F9C977378CCAB42C387828EDC2CC8D4B91059
    TLS session ticket lifetime hint: 100800 (seconds)
    TLS session ticket:
    ....(ignored)....

    Start Time: 1668083091
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
---

部分細節我就直接刪掉了,不過可以看出正常狀況它應該要能解析出 server 的憑證內容,並且顯示使用什麼協定來跟伺服器溝通。

附錄:Jetty 的 log

由於我用的是 Jetty,因此如果想追 Jetty 這邊的 log,可以打開 org.eclipse.jetty 的 debug log,從訊息中可以看出,Jetty 在啟用 HTTPS 時,會建立 SslContextFactory 的物件來進行(廢話)。更具體來說,應該會是 SslContextFactory.Server 物件。雖然說,出現這段看起來有啟動 HTTPS 的 log,實際上並不代表 HTTPS 就有正常被啟動了。我的實驗過程有遇到一個情況是 log 顯示 HTTPS 似乎啟動了,但結果真的用 curlopenssl 打都找不到憑證…。

2022-11-02 15:48:15,603 [main] DEBUG org.eclipse.jetty.util.component.AbstractLifeCycle - starting SslConnectionFactory@40ee0a22{SSL->HTTP/1.1}
2022-11-02 15:48:15,603 [main] DEBUG org.eclipse.jetty.util.component.AbstractLifeCycle - starting Server@7bde1f3a[provider=null,keyStore=file:////path/to/key/store/my_keystore.p12,trustStore=file:////path/to/trust/store/my_truststore.jks]
2022-11-02 15:48:15,636 [main] DEBUG org.eclipse.jetty.util.ssl.SslContextFactory - managers=[org.eclipse.jetty.util.ssl.AliasedX509ExtendedKeyManager@5cc152f9] for Server@7bde1f3a[provider=null,keyStore=file:////path/to/key/store/my_keystore.p12,trustStore=file:////path/to/trust/store/my_truststore.jks]
2022-11-02 15:48:15,640 [main] DEBUG org.eclipse.jetty.util.ssl.SslContextFactory - Selected Protocols [TLSv1.3, TLSv1.2] of [TLSv1.3, TLSv1.2, TLSv1.1, TLSv1, SSLv3, SSLv2Hello]
2022-11-02 15:48:15,640 [main] DEBUG org.eclipse.jetty.util.ssl.SslContextFactory - Selected Ciphers   [TLS_AES_256_GCM_SHA384, ....]
2022-11-02 15:48:15,640 [main] DEBUG org.eclipse.jetty.util.ssl.SslContextFactory - Customize sun.security.ssl.SSLEngineImpl@1117cc7c
2022-11-02 15:48:15,641 [main] DEBUG org.eclipse.jetty.util.component.AbstractLifeCycle - STARTED @119497ms Server@7bde1f3a[provider=null,keyStore=file:////path/to/key/store/my_keystore.p12,trustStore=file:////path/to/trust/store/my_truststore.jks]
2022-11-02 15:48:15,641 [main] DEBUG org.eclipse.jetty.util.ssl.SslContextFactory - Customize sun.security.ssl.SSLEngineImpl@4797023d
2022-11-02 15:48:15,641 [main] DEBUG org.eclipse.jetty.util.component.AbstractLifeCycle - STARTED @119497ms SslConnectionFactory@40ee0a22{SSL->HTTP/1.1}

2022年10月23日 星期日

Markdown Here 樣式筆記

紀錄目前 Markdown Here plugin 使用的設定。

Syntax Highlight 模板:Monokai Sublime

CSS:
這裡主要是模板以外再複寫一次 blockquote 的語法,讓部落格本來就在用的 blockquote 樣式維持原狀。

/*
 * NOTE:
 * - The use of browser-specific styles (-moz-, -webkit-) should be avoided.
 *   If used, they may not render correctly for people reading the email in
 *   a different browser than the one from which the email was sent.
 * - The use of state-dependent styles (like a:hover) don't work because they
 *   don't match at the time the styles are made explicit. (In email, styles
 *   must be explicitly applied to all elements -- stylesheets get stripped.)
 */

/* This is the overall wrapper, it should be treated as the `body` section. */
.markdown-here-wrapper {
}

/* To add site specific rules, you can use the `data-md-url` attribute that we
   add to the wrapper element. Note that rules like this are used depending
   on the URL you're *sending* from, not the URL where the recipient views it.
*/
/* .markdown-here-wrapper[data-md-url*="mail.yahoo."] ul { color: red; } */

pre, code {
  font-size: 0.85em;
  font-family: Consolas, Inconsolata, Courier, monospace;
}

code {
  margin: 0 0.15em;
  padding: 0 0.3em;
  white-space: pre-wrap;
  border: 1px solid #EAEAEA;
  background-color: #F8F8F8;
  border-radius: 3px;
  display: inline; /* added to fix Yahoo block display of inline code */
}

pre {
  font-size: 1em;
  line-height: 1.2em;
}

pre code {
  white-space: pre;
  overflow: auto; /* fixes issue #70: Firefox/Thunderbird: Code blocks with horizontal scroll would have bad background colour */
  border-radius: 3px;
  border: 1px solid #CCC;
  padding: 0.5em 0.7em;
  display: block !important; /* added to counteract the Yahoo-specific `code` rule; without this, code blocks in Blogger are broken */
}

/* In edit mode, Wordpress uses a `* { font: ...;} rule+style that makes highlighted
code look non-monospace. This rule will override it. */
.markdown-here-wrapper[data-md-url*="wordpress."] code span {
  font: inherit;
}

/* Wordpress adds a grey background to `pre` elements that doesn't go well with
our syntax highlighting. */
.markdown-here-wrapper[data-md-url*="wordpress."] pre {
  background-color: transparent;
}

/* This spacing has been tweaked to closely match Gmail+Chrome "paragraph" (two line breaks) spacing.
Note that we only use a top margin and not a bottom margin -- this prevents the
"blank line" look at the top of the email (issue #243).
*/
p {
  /* !important is needed here because Hotmail/Outlook.com uses !important to
     kill the margin in <p>. We need this to win. */
  margin: 0 0 1.2em 0 !important;
}

table, pre, dl, blockquote, q, ul, ol {
  margin: 1.2em 0;
}

ul, ol {
  padding-left: 2em;
}

li {
  margin: 0.5em 0;
}

/* Space paragraphs in a list the same as the list itself. */
li p {
  /* Needs !important to override rule above. */
  margin: 0.5em 0 !important;
}

/* Smaller spacing for sub-lists */
ul ul, ul ol, ol ul, ol ol {
  margin: 0;
  padding-left: 1em;
}

/* Use Roman numerals for sub-ordered-lists. (Like Github.) */
ol ol, ul ol {
  list-style-type: lower-roman;
}

/* Use letters for sub-sub-ordered lists. (Like Github.) */
ul ul ol, ul ol ol, ol ul ol, ol ol ol {
  list-style-type: lower-alpha;
}

dl {
  padding: 0;
}

dl dt {
  font-size: 1em;
  font-weight: bold;
  font-style: italic;
}

dl dd {
  margin: 0 0 1em;
  padding: 0 1em;
}

blockquote, q {
  border-left: 4px solid #DDD;
  padding: 0 1em;
  color: #777;
  quotes: none;
}

blockquote::before, blockquote::after, q::before, q::after {
  content: none;
}

blockquote{border-left: 15px solid #c76c0c;font-family: Georgia, serif;font-size:15px;text-align: justify;background: #fff;line-height: 1.2;
display:block;margin: 0 0 20px;padding: 15px 20px 15px 45px;position: relative; font-size: 16px;color: #666;
border-right: 2px solid #c76c0c;box-shadow: 2px 2px 15px #ccc;-webkit-box-shadow: 2px 2px 15px #ccc;-moz-box-shadow: 2px 2px 15px #ccc;}
blockquote::before{font-size: 50px;position: absolute;color: #999;left: 10px;top:5px;font-weight: bold;content: "\201C";}
blockquote a{cursor: pointer;color: #c76c0c;text-decoration: none;background: #eee;padding: 0 3px;}
blockquote a:hover{color: #555;}

h1, h2, h3, h4, h5, h6 {
  margin: 1.3em 0 1em;
  padding: 0;
  font-weight: bold;
}

h1 {
  font-size: 1.6em;
  border-bottom: 1px solid #ddd;
}

h2 {
  font-size: 1.4em;
  border-bottom: 1px solid #eee;
}

h3 {
  font-size: 1.3em;
}

h4 {
  font-size: 1.2em;
}

h5 {
  font-size: 1em;
}

h6 {
  font-size: 1em;
  color: #777;
}

table {
  padding: 0;
  border-collapse: collapse;
  border-spacing: 0;
  font-size: 1em;
  font: inherit;
  border: 0;
}

tbody {
  margin: 0;
  padding: 0;
  border: 0;
}

table tr {
  border: 0;
  border-top: 1px solid #CCC;
  background-color: white;
  margin: 0;
  padding: 0;
}

table tr:nth-child(2n) {
  background-color: #F8F8F8;
}

table tr th, table tr td {
  font-size: 1em;
  border: 1px solid #CCC;
  margin: 0;
  padding: 0.5em 1em;
}

table tr th {
 font-weight: bold;
  background-color: #F0F0F0;
}

2022年9月4日 星期日

[筆記] 詞彙的建立

在 IR 系統的前處理中,因為我們想要把資料建成 posting list,會需要先有相關的詞彙,才有辦法依據詞彙建立相應的 posting list。不過這時會有幾個常見的問題需要處理。

這篇會簡要紀錄一下書中提到的考量點。

1. Tokenization

Tokenization 是把句子分割並萃取的技術,萃取出來的單位被稱為 token,或者也可能被稱為 word、term,但事實上有時候我們可能會想要把 token 跟其他名詞做一點定義上的區分。以下是書中對於 token 的定義:

A token is an instance of a sequence of characters in some particular document that are grouped together as a useful semantic unit for processing.

除了 token 以外,另外還有 typeterm 這兩個名詞。書中提供的定義分別如下:

A type is the class of all tokens containing the same character sequence.

A term is a (perhaps normalized) type that is included in the IR system’s dictionary.

直接用書中提供的例子應該會比較好懂。舉例來說,如果我們想對下述的句子做 tokenization:

to sleep perchance to dream

此時,會有 to, sleep, perchance, to, dream 共 5 個 token;但只會有 4 個 type:to, sleep, perchance, dream,因為有兩個 to 是重複的;而如果 IR 系統中有處理 stop words,我們可能會把 to 視為是 stop words 而將它移除,此時最終在 IR 系統中被 index 的 term 就只會有 3 個:sleep, perchance, dream

那麼我們通常會如何做 tokenziation 呢?初步看起來,似乎就是直接針對空白做分割,然後可能把標點符號什麼的都去除掉就可以了?然而現實上,還是會出現一些比較困難的問題,導致我們可能還需要考慮別的因子。例如:

  • ' 在英文中,可以代表所有格關係、也可以代表縮寫。
  • 不同語言有自己的語言特徵。
  • 特定領域可能有自己特殊的 type。
  • - 在英文中也存在多種不同用法。
  • 多個字組成的詞彙無法單純用空白切割來處理。

以下會分別針對這些狀況做點簡單的描述。

1.1. Apostrophe (‘)

' 這個符號在英文中有多種用法,例如以下這個句子:

Mr. O'Neill thinks that the boys' stories about Chile's capital aren't amusing.

這裡同時出現了三種不同的用法:

  • O’Neill 中的 ' 是名字的一部分。
  • boys’ 和 Chile’s 中的 ' 是所有格。
  • aren’t 中的 ' 是縮寫。

此時針對 ' 做的處理的不同,可能會導致後續 IR 系統的 matching 受到影響。例如如果我們將 ' 拆開的話,aren't 被拆成 arent 看起來就會很奇怪。同時,O'Neill 被拆成 ONeill 會導致搜尋時使用 o'neil 會無法 match 到相應的 token。

1.2. 語言特徵

tokenization 的行為往往跟語言有很大的關係,不同語言的 tokenization 作法會有蠻大的不同。例如中文和日文就沒有空白分隔的特性,每個字都是連在一起的。

1.3. 領域特徵

在特定領域,有可能有領域內專屬的詞彙需要能夠被識別成 term,例如 C++C#、或者飛機型號 B-52(戰略轟炸機)。另外網際網路中的 URL(https://xxx)、e-mail(abc@abc.com)、IP 位址(a.b.c.d)等等可能也會需要能夠被視為是獨立的 term。

1.4. 連字符號 Hyphenation (-)

英文中連字符號的處理可能會很複雜,書中舉出幾種連字符號的用法:

  • 分隔單字之間的母音,像是 co-education。這個例子實際上它代表的是 coeducaion
  • 將多個名詞連接成一個新的名稱,例如 Hewlett-Packard
  • 多個詞語的組成結果,例如 the hold-him-back-and-drag-him-away maneuver。這個例子應該要被拆解成各自獨立的 term。

1.5. 特殊詞彙

這類的資訊其實我覺得也可以算是領域特徵的一種。例如書中舉的一個例子是 New York University(紐約大學)跟 York University(約克大學)。如果他們沒有被獨立視為 term,而是純粹依據空白拆開的話,那麼搜尋 York University 時就會 match 到 New York University 了,但這顯然並非是使用者想找的東西。

2. Stop Words

停用詞(Stop Words)的目的,是去除出現頻率過高、但又跟文件本身關係不大的詞彙。不過由於去除停用詞的行為,有時會導致意義的流失,所以現代的 IR 系統比較會考慮不去除停用詞,改為將停用詞賦予較低的權重,使其影響變小。舉例來說,flights to London 如果把 to 給去除了,flights to London 的意義就流失了。


其實還有兩個小節,不過等有空時再補筆記了…。
是說搜尋是個在現代非常常見的行為,但最近的研究總覺得這個領域有點冷門?

2022年6月5日 星期日

修復 Windows 10 的開機磁區

因為我要幫家人升級電腦,這次升級會連系統碟都換成 SSD,所以需要把舊硬碟裡的資料一起搬移到新的 SSD 上。本來我想說應該只需要把 C 槽裡的資料備份起來就好,就找了個備份軟體 Macrium Reflect [1] 來做硬碟備份,然後把映像檔放進隨身碟裡以後帶回我家,開始裝主機跟用映像檔還原系統碟出來。

不過實際要執行還原時,發現一個問題是我沒有備份開機磁區出來...。於是那時想了個方法是,先安裝一個全新的 Windows 10,這樣安裝過程就會重新切割硬碟,並且切出應該要有的開機磁區等等的。畢竟我也不太清楚裡面裝了什麼,讓 Windows 10 安裝程式幫忙弄應該比較安全。等到裝好以後,我再用 Macrium Reflect 把映像檔裡的資料蓋到 C 槽上!完美!

結果幻想很美好、現實很殘酷,實際蓋上去以後,發生了 Windows 根本開不了機的問題。事後看起來應該是因為開機磁區(這裡用的是 GPT,因為我想用 UEFI 開機)裡的設定是用 UUID 在辨識系統碟的,所以應該是遇到開機磁區上寫的 UUID 跟實際 C 槽的 UUID 不同的關係,畢竟我把映像檔的資料蓋到 C 槽裡了。於是就進入了研究如何修復開機磁區的過程。

其實我也沒有搞很懂步驟到底在幹麻 XD。不過簡要來說,就是在啟動修復的畫面裡打開命令提示字元,然後把隱藏的開機磁區掛載上去,這樣我們才能夠存取裡面的檔案。接著執行 bootrec /fixboot 來修復 [2]。但我記得我的這個步驟好像是失敗了就是,會遇到 access denied 的問題,然後我好像沒有成功解決它。

最後我實際有做成功的,應該是把開機磁區掛載到 V: 後,執行 bcdboot C:\windows /s V: /f UEFI 這個指令 [3],這應該是在開機程序裡新增一個開機碟吧。所以我再重開機時,Windows 會跑出有兩個 Windows 要我選擇。接著在 Windows 裡再用 msconfig [4] 把非現在使用的開機系統移除就好了。

參考資料

  1. Macrium Reflect
  2. How to Fix Startup Repair in Windows 10 | System Reserved
  3. windows10 Bootrec /Fixboot 存取被拒(Access Is Denied) 
  4. Delete Boot Menu Entry in Windows 10

2022年5月19日 星期四

Windows 10 的 Realtek 和 Intel 驅動程式

前陣子換了主機板,換成 MSI MAG H670 TOMAHAWK WIFI DDR4,換完以後本來預期應該不用特別做什麼,Windows 10 就能夠順順讓新的硬體運作了。但結果現實沒有想像中那麼美好,最後遇到兩個驅動程式方面的問題。 

首先是遇到一開始本來都好好的,結果重開機後電腦就沒聲音了!但驅動程式那邊又顯示裝置正常運作,然後工作列的喇叭小圖示也有正常顯示。找了非常久的問題,最後大體上辨識了問題應該是出在 Realtek HD Audio 的驅動程式可能有什麼衝突或問題之類的,而且這個問題看似不是只有我遇到,好像不少人都遇到,甚至還有網友整理可用的驅動程式 [2]...。但從結論來說就是,網路上找到的這些解法 [1-3] 對我來說都沒有用。最終我的聲音恢復正常的原因是因為我直接洗掉整顆硬碟重灌 Windows 10 了。重灌後目前用的是 Windows 內建的驅動程式,因為不敢再裝原廠的驅動程式,怕又掉進之前重開機就沒聲音的迴圈...。反正對我來說只要有聲音就好,我也不太需要什麼特效之類的。

接著因為我重灌 Windows 10,遇到另一個我覺得更奇耙的問題...。MSI MAG H670 TOMAHAWK WIFI DDR4 內建有 Intel® I225V 2.5Gbps 網路晶片跟 Intel® Wi-Fi 6 無線網路晶片。在 Windows 10 裝好以後,我要裝網路晶片的驅動程式時,發現 Wifi 的驅動程式告訴我說 Windows 版本過舊沒辦法裝、I225V 的驅動程式則說找不到相應的晶片。此時完全是黑人問號...。也是花了不少時間搜尋後,找到了 [4] 的教學,原來其實兩個問題是同一個,問題是在於 Windows 10 需要升級到 1809 版本(2018/10 更新)以上才有辦法安裝驅動程式。但我的 Windows 10 映像檔是最原始版本 1507,所以裝不進去....。這裡解決方法可以嘗試看看 [4],它有教如何自己去改 INF 設定檔的內容,強迫安裝驅動程式。不過我最後的解法是拿出了一個很老舊的 USB 無線網卡,用它連上網路開始做 Windows Update....。

  1. 【問題】安裝新的音效驅動後,隔天就沒聲音?音效軟衝突?瑞昱高清音效求解,求救QAQ
  2.  [更新]Realtek High Definitoin Audio音效驅動的最新版下載點
  3. How to Fix Realtek High Definition Audio Driver Issue & Fix Issues With Any Realtek Sound Card 2022 
  4. Intel i225-v Network Card WORKAROUND for Windows 10 1709?