第十五章:使用 SSL
在從以 socket 為基礎(chǔ)的 appender 到遠(yuǎn)程 receiver 傳遞日志事件時(shí)陕贮,logback 支持使用安全套接字層壹置。當(dāng)使用支持 SSL 的 appender 以及響應(yīng)的 receiver 時(shí)科汗,通過安全通道來傳遞日志事件脐嫂。
SSL 與組件的角色
logback 的組件晃酒,例如 appender 以及 receiver 在網(wǎng)絡(luò)連接初始化時(shí)可能承當(dāng)服務(wù)器的角色或者客戶端的角色。當(dāng)充當(dāng)服務(wù)器角色時(shí)隙咸,logback 組件被動(dòng)的監(jiān)聽來自遠(yuǎn)程客戶端組件的連接沐悦。相反地成洗,充當(dāng)客戶端角色的 logback 組件會(huì)初始化一個(gè)連接到遠(yuǎn)程服務(wù)器組件。例如藏否,一個(gè)充當(dāng)客戶端角色的 appender 連接充當(dāng)服務(wù)端角色的 receiver瓶殃。或者一個(gè)充當(dāng)客戶端角色的 receiver 連接充當(dāng)服務(wù)端角色的 appender副签。
組件的角色通常由組件的類型決定遥椿。例如,SSLServerSocketAppender
是一個(gè)充當(dāng)服務(wù)端角色的 appender 組件淆储,但是 SSLSocketAppender
是一個(gè)充當(dāng)客戶端角色的 appender 組件冠场。因此開發(fā)者或者應(yīng)用管理人員可以配置 logback 組件來支持想要的網(wǎng)絡(luò)連接初始化方向。
網(wǎng)絡(luò)連接初始化方法在 SSL 上下文中非常重要本砰,因?yàn)樵?SSL 中碴裙,服務(wù)端組件連接客戶端必須具有 X.509 證書來標(biāo)識(shí)自身〉愣睿客戶端組件舔株,在連接服務(wù)端時(shí),使用服務(wù)端的證書來驗(yàn)證服務(wù)端是否可信还棱。開發(fā)人員或者應(yīng)用管理者必須清楚的知道 logback 組件的角色督笆,才能正確配置服務(wù)器的 keystore (包含服務(wù)器 X.509 證書) 以及客戶端的 truststore (包含用于驗(yàn)證服務(wù)器信任時(shí)的自簽名根證書)。
當(dāng)為 相互認(rèn)證 配置 SSL诱贿,服務(wù)器組件與客戶端組件必須擁有有效的 X.509 證書,它們的信任由它們各自對(duì)等的聲明咕缎。相互認(rèn)證配置在服務(wù)器組件中珠十,因此開發(fā)人員或者應(yīng)用管理者必須知道哪一個(gè)組件充當(dāng)?shù)氖欠?wù)器的角色。
在本章凭豪,我們使用術(shù)語 服務(wù)器組件 或者簡(jiǎn)單的 服務(wù)器 來表示 logback 中充當(dāng)服務(wù)器角色的 appender 或者 receiver焙蹭。使用 客戶端組件 或者建的 客戶端 來表示充當(dāng)客戶端角色的組件。
SSL 以及 X.509 證書
為了是用支持 SSL 的 logback 組件嫂伞,你需要一個(gè) X.509 的證書 (一個(gè)私鑰孔厉,相應(yīng)的證書,以及 CA 認(rèn)證鏈) 去標(biāo)識(shí)你的組件充當(dāng)了一個(gè) SSL 服務(wù)器帖努。如果你想要使用雙向認(rèn)證撰豺,那么充當(dāng) SSL 客戶端的組件還需要一個(gè)證書。
雖然你可以使用由商業(yè)認(rèn)證機(jī)構(gòu) (CA) 頒發(fā)的證書拼余,但是你也可以使用內(nèi)部 CA 頒發(fā)的證書污桦,甚至是自簽名的證書。下面是必須滿足的條件:
- 服務(wù)端組件必須配置一個(gè) key store匙监,包含服務(wù)器私鑰凡橱,相應(yīng)的證書小作,以及 CA 認(rèn)證鏈 (如果沒有使用自簽名證書)
- 客戶端組件必須配置一個(gè) trust store,包含可信任的根 CA 證書稼钩,或者服務(wù)器自簽名根證書
為 SSL 配置 logback 組件
Java 安全套接字拓展 (JSSE) 以及 Java 加密體系 (JCA) 用來實(shí)現(xiàn) logback 的 SSL顾稀,支持諸多的配置選項(xiàng)“映牛可插拔的提供框架允許替換或增強(qiáng)內(nèi)置的 SSL 以及平臺(tái)的加密功能静秆。為了滿足你的對(duì)安全的需要,支持 SSL 的 logback 組件提供完全指定 SSL 引擎以及密碼提供者配置方面的能力绍载。
使用 JSSE 系統(tǒng)屬性的基本 SSL 配置
幸運(yùn)的是诡宗,支持 SSL 的 logback 組件幾乎所有的 SSL 屬性的配置都有合理的默認(rèn)值。在多數(shù)的情況下击儡,只需要配置一些 JSSE 的系統(tǒng)屬性塔沃。
本節(jié)剩余的部分將講述在大多數(shù)的環(huán)境中都需要被指定的 JSSE 屬性。查看定制 JSSE來獲取更多關(guān)于設(shè)置 JSSE 系統(tǒng)屬性的信息來定制 JSSE阳谍。
如果你使用任何 logback 中支持 SSL 的 appender 或者 receiver 組件充當(dāng)服務(wù)端角色 (例如蛀柴,SSLServerSocketReceiver
,SSLServerSocketAppender
矫夯,SimpleSSLSocketServer
)鸽疾。你需要提供 key store 包含的密鑰以及證書的 location,type 以及 password 來配置 JSEE 系統(tǒng)屬性训貌。
服務(wù)端 key store 配置的系統(tǒng)屬性
屬性名 | 描述 |
---|---|
javax.net.ssl.keyStore |
指定包含服務(wù)端組件的密鑰以及證書的文件的文件系統(tǒng)的路徑 |
javax.net.ssl.keyStoreType |
指定 key store 類型制肮。如果這個(gè)屬性沒有指定,將默認(rèn)為 JKS |
javax.net.ssl.keyStorePassword |
指定訪問 key store 的密碼 |
查看下面 Examples 部分递沪,在應(yīng)用啟動(dòng)的時(shí)候通過利用 logback 支持 SSL 的服務(wù)端組件來設(shè)置這些系統(tǒng)屬性豺鼻。
如果你的服務(wù)端組件使用的證書是商業(yè)認(rèn)證機(jī)構(gòu) (CA) 認(rèn)證,你可能不需要在你應(yīng)用的客戶端組件中提供任何 SSL 配置款慨。當(dāng)在你的服務(wù)端組件使用商業(yè)簽名證書儒飒,僅僅只需要在運(yùn)行服務(wù)端組件的 JVM 上設(shè)置系統(tǒng)的 key store 屬性。
如果你使用自簽名的服務(wù)器證書或者你服務(wù)器證書是認(rèn)證機(jī)構(gòu) (CA) 簽名但是它們的根證書不再 Java 平臺(tái)默認(rèn)的 trust store 中 (例如檩奠,你的組織有自己的內(nèi)部簽名機(jī)構(gòu))桩了。你需要配置 JSSE 系統(tǒng)屬性,以提供包含你服務(wù)器證書的 trust store 或者認(rèn)證機(jī)構(gòu) (CA) 頒發(fā)的受信任根證書簽名的服務(wù)器證書的 location埠戳,type井誉,以及 password。這些屬性需要在每個(gè)利用支持 SSL 的客戶端組件中的應(yīng)用中設(shè)置乞而。
客戶端 trust store 配置的系統(tǒng)屬性
屬性名 | 描述 |
---|---|
javax.net.ssl.trustStore |
指定包含服務(wù)端組件的證書或者受信任根證書的文件的文件系統(tǒng)的路徑 |
javax.net.ssl.trustStoreType |
指定 trust store 類型送悔。如果這個(gè)屬性沒有被指定,則默認(rèn)為 JKS |
javax.net.ssl.trustStorePassword |
指定訪問 trust store 的密碼 |
查看下面 Examples 部分,在應(yīng)用啟動(dòng)的時(shí)候通過利用 logback 支持 SSL 的客戶端組件來設(shè)置這些系統(tǒng)屬性欠啤。
高級(jí) SSL 配置
在特定的情況下荚藻,使用 JSEE 系統(tǒng)屬性的基本 SSL 配置是不恰當(dāng)?shù)摹1热缃喽危阆胍?web 應(yīng)用中使用 SSLServerSocketReceiver
組件应狱,你可能想要使用不同的證書為你的遠(yuǎn)程日志客戶端標(biāo)識(shí)你的日志服務(wù)器,而不是 web 服務(wù)器為了 web 客戶端使用證書來標(biāo)識(shí)自身祠丝。你可能想要在日志服務(wù)器上驗(yàn)證 SSL 客戶端疾呻,確保只有真正授權(quán)的遠(yuǎn)程 logger 才可以連接⌒窗耄或者你的組織對(duì)于在組織所在的網(wǎng)絡(luò)上使用 SSL 協(xié)議以及密碼套件有嚴(yán)格的策略岸蜗。為了滿足這些需求,你需要使用 logback SSL 高級(jí)配置選項(xiàng)叠蝇。
在配置 logback 組件支持 SSL 時(shí)璃岳,你需要在組件的配置中指定 ssl
屬性來指定 SSL 的配置。
例如悔捶,如果你想要使用 SSLServerSocketReceiver
以及為日志服務(wù)器認(rèn)證配置 key store 屬性铃慷,你可以使用類似如下的配置:
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="CONSOLE" />
</root>
<receiver class="ch.qos.logback.classic.net.server.SSLServerSocketReceiver">
<ssl>
<keyStore>
<location>classpath:/logging-server-keystore.jks</location>
<password>changeit</password>
</keyStore>
</ssl>
</receiver>
</configuration>
該配置將 key store 的位置指定為位于應(yīng)用類路徑下的 logging-server-keystore.jks。你也可以通過 file:
URL 來指定 key store 的位置蜕该。
如果你想要在你的應(yīng)用中使用 SSLSocketAppender
犁柜,但是不想要改變默認(rèn) trust store 使用的 JSSE javax.net.ssl.trustStore
屬性。你可以通過如下的方式進(jìn)行配置:
<configuration>
<appender name="SOCKET" class="ch.qos.logback.classic.net.SSLSocketAppender">
<ssl>
<trustStore>
<location>classpath:/logging-server-truststore.jks</location>
<password>changeit</password>
</trustStore>
</ssl>
</appender>
<root level="debug">
<appender-ref ref="SOCKET" />
</root>
</configuration>
該配置將 key store 的位置指定為位于應(yīng)用類路徑下的 logging-server-keystore.jks堂淡。你也可以通過 file:
URL 來指定 key store 的位置馋缅。
SSL 配置屬性
JSSE 公開 了大量的可配置選項(xiàng)。logback 的 SSL 支持幾乎所有這些可用的選項(xiàng)在支持 SSL 組件的配置中指定绢淀。在使用 XML 配置時(shí)股囊,在組件的配置中,SSL 屬性被嵌套在 <ssl>
元素中引入更啄。這個(gè)配置元素對(duì)應(yīng) SSLConfiguration
類。
當(dāng)為你的組件配置 SSL 時(shí)居灯,你僅僅只需要配置那些默認(rèn)值不適合的 SSL 屬性祭务。過度指定 SSL 配置經(jīng)常會(huì)導(dǎo)致一些難以診斷的問題。
下面的表格展示了頂層的 SSL 配置屬性怪嫌。許多頂層的屬性還有額外的子屬性义锥,這些子屬性將會(huì)頂層屬性之后描述。
屬性名 | 類型 | 描述 |
---|---|---|
keyManagerFactory | KeyManagerFactoryFactoryBean |
指定用于創(chuàng)建 KeyManagerFactory 的配置岩灭。如果這個(gè)屬性沒有配置拌倍,那么將會(huì)使用 Java 平臺(tái)默認(rèn)的 factory。見 Key Manager Factory 配置
|
keyStore | KeyStoreFactoryBean |
指定用于創(chuàng)建 KeyStore 的配置。通過這個(gè)屬性創(chuàng)建的 KeyStore 必須包含唯一的 X.509 證書 (包含密鑰柱恤,相應(yīng)的證書以及 CA 認(rèn)證鏈)数初。這個(gè)證書由本地 SSL 提供給遠(yuǎn)程的 SSL。<br />當(dāng)配置一個(gè) SSL 客戶端時(shí) (例如梗顺,SSLSocketAppender )泡孩,僅僅只有在遠(yuǎn)程配置需要驗(yàn)證客戶端身份時(shí)才需要該屬性。<br />當(dāng)配置一個(gè) SSL 服務(wù)端時(shí) (例如寺谤,SimpleSSLSocketServer )仑鸥,該屬性指定的 key store 包含了服務(wù)端證書。如果沒有配置這個(gè)屬性变屁,JSSE 的 javax.net.ssl.keyStore 系統(tǒng)屬性必須配置用于提供服務(wù)端 key store 的位置眼俊。查看 定制 JSEE 來獲取更多關(guān)于 JSEE 系統(tǒng)屬性的信息。<br />更多的信息查看 Key Store 配置粟关。 |
parameters | SSLParametersConfiguration |
在 SSL 會(huì)話中疮胖,指定各種參數(shù)。見下面的 SSL 參數(shù)配置誊役。 |
protocol | String |
指定創(chuàng)建 SSLContext 的 SSL 協(xié)議获列。見命名規(guī)范。如果沒有配置該參數(shù)蛔垢,那么將使用 Java 平臺(tái)默認(rèn)的協(xié)議击孩。 |
provider | String |
指定創(chuàng)建 SSLContext 的 JSSE 提供者。如果沒有配置該參數(shù)鹏漆,那么將使用 Java 平臺(tái)默認(rèn)的 JSSE 提供者巩梢。 |
secureRandom | SecureRandomFactoryBean |
指定創(chuàng)建 SecureRandom (安全的隨機(jī)數(shù)生成器) 的配置。如果沒有配置該參數(shù)艺玲,那么將使用 Java 平臺(tái)默認(rèn)的生成器括蝠。見下面的 安全隨機(jī)數(shù)生成配置。 |
trustManagerFactory | TrustManagerFactoryFactoryBean |
指定創(chuàng)建 TrustManagerFactory 的配置饭聚。如果沒有指定該參數(shù)忌警,那么將使用 Java 平臺(tái)默認(rèn)的 factory。見下面的 受信任的管理工廠秒梳。 |
trustStore | KeyStoreFactoryBean |
指定創(chuàng)建 KeyStore 的配置法绵,用于驗(yàn)證遠(yuǎn)程 SSL 的身份。通過這個(gè)屬性創(chuàng)建的 KeyStore 應(yīng)該包含一個(gè)或多個(gè)信任錨 (trust anchors) — keystore 中被標(biāo)記為受信任的自簽名證書酪碘。通常朋譬,trust store 包含自簽名的 CA 證書。<br />通過該屬性指定的 trust store 會(huì)覆蓋任何通過 JSSE 的 javax.net.ssl.trustStore 以及平臺(tái)默認(rèn)的 trust store兴垦。 |
Key Store 配置
KeyStoreFactoryBean
指定創(chuàng)建包含 X.509 證書的 KeyStore
所需要的配置徙赢。這個(gè) factory bean 的屬性能夠用于 SSL 配置 中的 keyStore 以及 trustStore 屬性字柠。
屬性名 | 類型 | 描述 |
---|---|---|
location | String |
指定 key store 的位置 URL。使用 file: 指定 keystore 在文件系統(tǒng)中的位置狡赐。使用 classpath: 指定 keystore 在類路徑下的位置窑业。如果 URL 沒有指定具體的策略,那么將使用 classpath: 阴汇。 |
password | String |
指定訪問 keystore 的密碼 |
provider | String |
指定用于創(chuàng)建 KeyStore 的 JCA 提供者的名字数冬。如果沒有指定該屬性,那么將使用 Java 平臺(tái)默認(rèn)的 keystore 提供者搀庶。 |
type | String |
指定 KeyStore 的類型拐纱。見 命名規(guī)范。如果沒有指定該屬性哥倔,那么將使用 Java 平臺(tái)默認(rèn)的 keystore 類型秸架。 |
Key Manager Factory 配置
KeyManagerFactoryFactoryBean
指定創(chuàng)建 KeyManagerFactory
需要的配置。通常咆蒿,沒有必要詳細(xì)的配置 key manager factory东抹,因?yàn)槠脚_(tái)默認(rèn)的 factory 就可以滿足大部分的需求。
屬性名 | 類型 | 描述 |
---|---|---|
algorithm | String |
指定 KeyManagerFactory 算法的名字沃测。見 命名規(guī)范缭黔。如果沒有指定該屬性,那么將會(huì)使用 Java 平臺(tái)默認(rèn)的 key manager 算法蒂破。 |
provider | String |
指定生成 SecureRandom 生成器的 JCA 提供者的名字馏谨。如果沒有指定該屬性,那么將會(huì)使用 Java 平臺(tái)默認(rèn)的 JSSE 提供者附迷。 |
Secure Random Generator 配置
SecureRandomFactoryBean
指定創(chuàng)建 SecureRandom
生成器所需要的配置惧互。通常,沒有必要詳細(xì)的配置 secure random 生成器喇伯,因?yàn)槠脚_(tái)默認(rèn)的生成器就可以滿足大部分的需求喊儡。
屬性名 | 類型 | 描述 |
---|---|---|
algorithm | String |
指定 SecureRandom 算法的名字。見 命名規(guī)范稻据。如果沒有指定該屬性艾猜,那么將會(huì)使用 Java 平臺(tái)默認(rèn)的隨機(jī)數(shù)生成器 (random number generation) 算法。 |
provider | String |
指定用于創(chuàng)建 SecureRandom 生成器的 JCA 提供者捻悯。如果沒有指定該屬性箩朴,那么將會(huì)使用 Java 平臺(tái)默認(rèn)的 JSSE 提供者。 |
SSL 參數(shù)配置
SSLParametersConfiguration
允許定制受允許的 SSL 協(xié)議秋度,密碼套件,以及客戶端認(rèn)證選項(xiàng)钱床。
Property Name | Type | Description |
---|---|---|
excludedCipherSuites | String |
指定以逗號(hào)分隔的 SSL 密碼套件的名字或者模式列表荚斯,用來在會(huì)話期間進(jìn)行禁用。這個(gè)屬性通過 SSL 引擎過濾密碼套件。任何被該屬性匹配到的密碼套件都會(huì)被禁用事期。<br />以逗號(hào)分割的各個(gè)字段可以是字符串或者正則表達(dá)式滥壕。<br />查看密碼套件的命名規(guī)則 |
includedCipherSuites | String |
與上一個(gè)屬性除了作用相反,其它都是一樣 (懶得翻譯了)兽泣。 |
excludedProtocols | String |
這個(gè)是表示需要排除的 SSL 協(xié)議绎橘。與上一個(gè)屬性,除了作用不同唠倦,其它都一樣称鳞。 |
includedProtocols | String |
與上一個(gè)協(xié)議作用相反,其它一致稠鼻。 |
needClientAuth | boolean |
設(shè)置屬性為 true 表示冈止,服務(wù)端需要一個(gè)有效的客戶端證書。當(dāng)客戶端組件為 SSLSocketAppender 時(shí)候齿,該屬性會(huì)被忽略熙暴。 |
wantClientAuth | boolean |
設(shè)置屬性為 true 表示,服務(wù)端想要一個(gè)有效的客戶端證書慌盯。當(dāng)客戶端組件為 SSLSocketAppender 時(shí)周霉,該屬性會(huì)被忽略。(與上一個(gè)屬性的差異亚皂,需要自己動(dòng)手去實(shí)踐俱箱。因?yàn)槲乙膊磺宄??) |
Trust Manager Factory 配置
TrustManagerFactoryFactoryBean
指定創(chuàng)建 TrustManagerFactory
所需要的配置。通常孕讳,沒有必要明確的配置 trust manager factory匠楚,平臺(tái)默認(rèn)的 factory 就可以滿足大部分的需要。
屬性名 | 類型 | 描述 |
---|---|---|
algorithm | String |
指定 TrustManagerFactory 算法的名字厂财。見 命名標(biāo)準(zhǔn)芋簿。如果沒有指定該屬性,那么將使用 Java 平臺(tái)默認(rèn)的 key manager 算法璃饱。 |
provider | String |
指定創(chuàng)建 SecureRandom 生成器的 JCA 提供者的名字与斤。如果沒有指定該屬性,那么將使用 Java 平臺(tái)默認(rèn)的 JSSE 提供者荚恶。 |
示例
使用 JSSE 系統(tǒng)屬性
JSEE 系統(tǒng)屬性可以用來指定包含服務(wù)端 X.509 證書的 keystore 的位置以及密碼撩穿。或者包含客戶端組件驗(yàn)證服務(wù)端信任的自簽名根 CA 證書的 truststore 的位置以及密碼谒撼。
指定服務(wù)端 keystore
在運(yùn)行服務(wù)端組件時(shí)食寡,需要指定包含服務(wù)端證書的 keystore 的位置以及密碼。一種方法是使用 JSSE 系統(tǒng)屬性廓潜。下面的例子通過命令行的方式啟動(dòng) SimpleSSLSocketServer
:
java -DkeyStore=/etc/logback-server-keystore.jks \
-DkeyStorePassword=changeit -DkeyStoreType=JKS \
ch.qos.logback.net.SimpleSSLSocketServer 6000 /etc/logback-server-config.xml
注意抵皱,在使用 JSSE keyStore 系統(tǒng)屬性時(shí)善榛,指定了 keystore 的路徑。在指定了 logback.xml 的路徑時(shí)呻畸,keystore 的 URL 被指定移盆。
雖然這個(gè)示例啟動(dòng)了一個(gè)提供 logback 的單機(jī)服務(wù)端應(yīng)用,但是同樣的系統(tǒng)屬性可以在任何使用支持 SSL 的 logback 服務(wù)端組件上指定并啟動(dòng)伤为。
指定客戶端 truststore
當(dāng)使用客戶端組件時(shí)咒循,需要指定包含根 CA 證書的 truststore 的位置與密碼,用于驗(yàn)證服務(wù)端的信任绞愚。一種方式是通過使用 JSSE 系統(tǒng)屬性叙甸。下面的示例通過命令行啟動(dòng)一個(gè)名為 com.example.MyLoggingApplication
的應(yīng)用,該應(yīng)用使用一個(gè)或多個(gè)支持 SSL 的 logback 客戶端組件爽醋。
java -DtrustStore=/etc/logback-client-truststore.jks \
-DtrustStorePassword=changeit -DtrustStoreType=JKS \
com.example.MyLoggingApplication
注意蚁署,在使用 JSSE trustStore 系統(tǒng)屬性時(shí),指定了 truststore 的路徑蚂四。在指定了 logback.xml 的路徑時(shí)光戈,truststore 的 URL 被指定。
創(chuàng)建以及使用自簽名的服務(wù)端組件證書
為了生成自簽名的證書遂赠,可以使用 JRE 自帶的 keytool 工具久妆。下面的指令在服務(wù)端組件的 keystore 中創(chuàng)建一個(gè)自簽名的 X.509 證書。以及創(chuàng)建在客戶端組件中使用的 truststore跷睦。
創(chuàng)建服務(wù)端組件證書
下面的命令在一個(gè)名為 server.keystore 的文件中生成自簽名客戶端證書筷弦。
keytool -genkey -alias server -dname "CN=my-logging-server" \
-keyalg RSA -validity 365 -keystore server.keystore
Enter keystore password: <Enter password of your choosing>
Re-enter new password: <Re-enter same password>
Enter key password for <my-logging-server>
(RETURN if same as keystore password): <Press RETURN>
在 dname 中使用的名字 my-logging-server 可以是任何你選擇的有效的名字。你可能想要使用服務(wù)端主機(jī)上的全限定名抑诸。validity 參數(shù)可以指定從當(dāng)前日期開始直到證書過期的天數(shù)烂琴。
在實(shí)際的設(shè)置中,為包含服務(wù)端證書的 keystore 選擇一個(gè)強(qiáng)密碼是非常重要的蜕乡。密碼用來保護(hù)服務(wù)端的密碼奸绷,防止被已授權(quán)方使用。記下剛才設(shè)置的密碼层玲,因?yàn)樵诮酉聛砼渲梅?wù)端的時(shí)候需要使用号醉。
為客戶端組件創(chuàng)建 truststore
由于要配置客戶端組件,在前一個(gè)步驟中創(chuàng)建的服務(wù)端證書需要從 keystore 中導(dǎo)出辛块,并且導(dǎo)入到 truststore 中畔派。下面的命令將會(huì)導(dǎo)出證書并且導(dǎo)入到名為 server.truststore 的 truststore。
keytool -export -rfc -alias server -keystore server.keystore \
-file server.crt
Enter keystore password: <Enter password you chose for in previous step>
keytool -import -alias server -file server.crt -keystore server.truststore
Enter keystore password: <Enter password of your choosing>
Re-enter new password: <Re-enter same password>
Owner: CN=my-logging-server
Issuer: CN=my-logging-server
Serial number: 6e7eea40
Valid from: Sun Mar 31 07:57:29 EDT 2013 until: Mon Mar 31 07:57:29 EDT 2014
...
Trust this certificate? [no]: <Enter "yes">
第一個(gè)命令從 keystore 中導(dǎo)出服務(wù)端證書 (但是不是服務(wù)端密鑰) 到一個(gè)名為 server.crt 的文件润绵。第二個(gè)步驟創(chuàng)建一個(gè)名為 server.truststore线椰,包含服務(wù)端證書的新的 truststore。
在實(shí)際的設(shè)置中尘盼,為 truststore 選擇一個(gè)不同于服務(wù)端 keystore 的強(qiáng)密碼非常的重要憨愉。記住這個(gè)密碼呜魄,因?yàn)樵谂渲每蛻舳?appender 時(shí)需要使用。
配置服務(wù)端組件
拷貝 server.keystore 到你的服務(wù)端應(yīng)用的配置中莱衩。keystore 可以放在應(yīng)用的類路徑下,或者放在服務(wù)器主機(jī)文件系統(tǒng)的某個(gè)位置娇澎。在配置文件中指定 keystore 位置 URL 時(shí)笨蚁,可以使用 classpath:
或者 file:
。一個(gè)示例的服務(wù)端配置如下:
<configuration debug="true">
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="CONSOLE" />
</root>
<server class="ch.qos.logback.classic.net.server.SSLServerSocketReceiver">
<ssl>
<keyStore>
<location>classpath:server.keystore</location>
<password>${server.keystore.password}</password>
</keyStore>
</ssl>
</server>
</configuration>
示例假設(shè) keystore 放在應(yīng)用類路徑的根路徑下趟庄。
配置文件中使用 server.keystore.password 替換符指定 keystore 的密碼括细。這種方式可以避免將密碼直接存儲(chǔ)在配置文件中。例如戚啥,在啟動(dòng)的時(shí)候奋单,你的應(yīng)用可能會(huì)在控制臺(tái)提示密碼,之后在配置日志系統(tǒng)之前使用輸入的密碼將 server.keystore.password 設(shè)置為系統(tǒng)屬性猫十。
配置客戶端組件
你需要將 server.truststore 文件拷貝到使用支持 SSL 組件充當(dāng)客戶端角色的每個(gè)應(yīng)用的配置中览濒。truststore 可以放置在應(yīng)用的類路徑下,或者文件系統(tǒng)的某個(gè)地方拖云〈眩可以通過 classpath:
或者 file:
來指定 truststore 位置的 URL≈嫦睿客戶端 appender 的配置示例如下:
Example:
<configuration debug="true">
<appender name="SOCKET" class="ch.qos.logback.classic.net.SSLSocketAppender">
<remoteHost>${host}</remoteHost>
<ssl>
<trustStore>
<location>classpath:server.truststore</location>
<password>${server.truststore.password}</password>
</trustStore>
</ssl>
</appender>
<root level="DEBUG">
<appender-ref ref="SOCKET" />
</root>
</configuration>
示例中假設(shè) truststore 位于應(yīng)用類路徑的根路徑下乏苦。
配置中使用 server.truststore.password 替換符來指定 truststore 的密碼。這種方式可以避免直接將密碼存儲(chǔ)在配置文件中尤筐。例如汇荐,應(yīng)用啟動(dòng)時(shí)會(huì)在控制臺(tái)提示密碼,之后可以在配置日志系統(tǒng)之前通過輸入密碼將 server.truststore.password 設(shè)置為系統(tǒng)屬性盆繁。
審核 SSL 配置
在需要安全通行的設(shè)置中掀淘,經(jīng)常需要審核組件的 SSL 配置,驗(yàn)證與本地策略的一致性改基。在 logback 初始化時(shí)繁疤,logback 中的 SSL 通過提供 SSL 配置的詳細(xì)日志來滿足這一需求似枕≈簦可以在配置中使用 debug
屬性來開啟這個(gè)功能。
<configuration debug="true">
...
</configuration>
當(dāng)使用了 debug 屬性畸陡,在日志系統(tǒng)初始化時(shí)鸣哀,所有與 SSL 配置產(chǎn)生的相關(guān)信息都會(huì)被打印出來架忌。一個(gè)典型的示例如下:
Example:
06:46:31,941 |-INFO in SSLServerSocketReceiver@4ef18d37 - SSL protocol 'SSL' provider 'SunJSSE version 1.6'
06:46:31,967 |-INFO in SSLServerSocketReceiver@4ef18d37 - key store of type 'JKS' provider 'SUN version 1.6': file:src/main/java/chapters/appenders/socket/ssl/keystore.jks
06:46:31,967 |-INFO in SSLServerSocketReceiver@4ef18d37 - key manager algorithm 'SunX509' provider 'SunJSSE version 1.6'
06:46:31,973 |-INFO in SSLServerSocketReceiver@4ef18d37 - secure random algorithm 'SHA1PRNG' provider 'SUN version 1.6'
06:46:32,755 |-INFO in SSLParametersConfiguration@4a6f19d5 - enabled protocol: SSLv2Hello
06:46:32,755 |-INFO in SSLParametersConfiguration@4a6f19d5 - enabled protocol: SSLv3
06:46:32,755 |-INFO in SSLParametersConfiguration@4a6f19d5 - enabled protocol: TLSv1
06:46:32,756 |-INFO in SSLParametersConfiguration@4a6f19d5 - enabled cipher suite: SSL_RSA_WITH_RC4_128_MD5
06:46:32,756 |-INFO in SSLParametersConfiguration@4a6f19d5 - enabled cipher suite: SSL_RSA_WITH_RC4_128_SHA
06:46:32,756 |-INFO in SSLParametersConfiguration@4a6f19d5 - enabled cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA
為了簡(jiǎn)便起見,這里的輸出被截?cái)嗔艘徊糠治页摹5前藚f(xié)議叹放、提供者饰恕、算法、密碼套件以及在配置中所使用的 keystore 與 truststore 位置井仰。
雖然沒有一個(gè)審核日志是敏感的埋嵌,但是為了安全,在實(shí)際的設(shè)置中俱恶,在配置被驗(yàn)證之后雹嗦,日志信息不應(yīng)該被啟用。將 debug
屬性移除合是,或者設(shè)置為 false
了罪,將禁用日志審核。
解決 SSL 異常
當(dāng) SSL 配置錯(cuò)誤時(shí)聪全,普遍的結(jié)果是客戶端與服務(wù)端組件不能正常的通常泊藕。當(dāng)客戶端嘗試連接服務(wù)端時(shí),這個(gè)問題通常會(huì)被雙方拋出的異常表現(xiàn)出來难礼。
異常消息內(nèi)容的不容取決于你查看的是客戶端的日志還是服務(wù)端的日志娃圆。最主要的原因是在會(huì)話期間,錯(cuò)誤報(bào)告受限制于內(nèi)部的協(xié)議鹤竭。由于這種情況踊餐,為了定位會(huì)話問題,需要查看客戶端與服務(wù)端的日志臀稚。
Server's Certificate is Not Available
當(dāng)啟動(dòng)服務(wù)端組件時(shí)吝岭,你會(huì)在日志中看到如下的異常:
javax.net.ssl.SSLException: No available certificate or key corresponds to the SSL cipher suites which are enabled
大部分情況下表示你沒有配置包含服務(wù)端密鑰的 keystore 以及相應(yīng)的證書。
解決辦法
使用 keystore 系統(tǒng)屬性 或者服務(wù)端組件 ssl
屬性中的 keyStore 屬性吧寺。你必須指定包含服務(wù)端密鑰以及證書的 keystore 的路徑以及密碼窜管。
Client Does Not Trust the Server
當(dāng)客戶端嘗試連接服務(wù)端時(shí),在日志中看到如下的異常:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed
這個(gè)問題表示服務(wù)端展示的證書稚机,客戶端不相信幕帆。大部分情況下是使用自簽名的證書 (或者服務(wù)端證書由你組織內(nèi)部的認(rèn)證機(jī)構(gòu)所簽名) 并且你還沒有配置客戶端,導(dǎo)致它引用了包含服務(wù)端自簽名證書 (或者你的服務(wù)器證書是由 CA 簽名的受信任的根證書) 的 truststore赖条。
這個(gè)問題還會(huì)發(fā)生在服務(wù)端證書過期或者被取消的情況下失乾。在客戶端每次嘗試進(jìn)行連接時(shí),你在服務(wù)端的日志中會(huì)看到如下的異常信息:
javax.net.ssl.SSLHandshakeException: Received fatal alert: ...
異常信息的余下部分通常會(huì)提供一個(gè)代碼來表明為什么客戶端拒絕服務(wù)端證書:
代碼 | 描述 |
---|---|
certificate_unknown |
通常表示客戶端 truststore 沒有被正確的配置 |
certificate_expired |
表示服務(wù)端證書已過期纬乍,需要更換 |
certificate_revoked |
表示頒發(fā)的 CA 已經(jīng)撤銷了服務(wù)端證書碱茁,需要更換 |
解決辦法
如果服務(wù)端日志顯示 certificate_unknown
,那么使用 truststore 系統(tǒng)屬性 或者 appender 組件 ssl
屬性中的 trustStore 屬性仿贬,指定包含服務(wù)端自簽名證書或者頒發(fā)的 CA 根證書的 truststore 的路徑以及密碼纽竣。
如果服務(wù)端日志顯示 certificate_expired
或者 certificate_revoked
,表示服務(wù)端需要一個(gè)新的證書。新的證書以及相關(guān)的密鑰需要在服務(wù)端配置的 keystore 中更換蜓氨。并且聋袋,如果使用自簽名服務(wù)端證書,那么還需要更換在客戶端 appender 中配置的 truststore 服務(wù)端證書穴吹。
Server Does Not Trust the Client
注意:這個(gè)問題僅僅發(fā)生在你明確的配置服務(wù)端請(qǐng)求客戶端證書時(shí)幽勒。(使用 needClientAuth 或者 wantClientAuth 屬性)。
當(dāng)客戶端嘗試連接日志服務(wù)器時(shí)港令,可以在客戶端日志中看到如下的異常信息:
javax.net.ssl.SSLHandshakeException: Received fatal alert: ...
異常信息的其余部分會(huì)提供一個(gè)代碼表明為什么服務(wù)端拒絕客戶端證書代嗤。
代碼 | 描述 |
---|---|
certificate_unknown |
通常表示服務(wù)端 truststore 沒有正確的配置 |
certificate_expired |
表示客戶端證書已經(jīng)過期,需要更換 |
certificate_revoked |
表示頒發(fā)的 CA 已經(jīng)撤銷了客戶端證書缠借,需要更換 |
解決辦法
如果客戶端日志信息顯示 bad_certificate
,那么使用 truststore 系統(tǒng)屬性 或者服務(wù)端組件 ssl
屬性中的 trustStore 屬性宜猜,指定包含客戶端自簽名證書或者頒發(fā)的 CA 根證書的 truststore 的路徑以及密碼泼返。
如果服務(wù)端日志信息顯示 certificate_expired
或者 certificate_revoked
,表示客戶端需要一個(gè)新的證書姨拥。需要更換在客戶端配置中指定的 keystore 的新證書以及相應(yīng)的密鑰绅喉。
Client and Server Cannot Agree on a Protocol
注意:這個(gè)問題僅僅只在你的配置中明確的配置了 excludedProtocols 或者 includedProtocols SSL 協(xié)議時(shí)。
當(dāng)客戶端嘗試連接服務(wù)端時(shí)叫乌,你會(huì)在日志中看到如下異常信息:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
服務(wù)端的日志信息通常更加詳細(xì)柴罐,例如:
javax.net.ssl.SSLHandshakeException: SSLv2Hello is disabled
通常,表示你已經(jīng)排除其中的一個(gè)協(xié)議憨奸。
解決辦法
檢查服務(wù)端與客戶端指定的 excludedProtocols 以及 includedProtocols 屬性的值革屠。
Client and Server Cannot Agree on a Cipher Suite
注意:通常這個(gè)問題只發(fā)生在你明確的在配置文件中指定了 excludedCipherSuites 或者 includedCipherSuites SSL 密碼套件時(shí)。
當(dāng)客戶端嘗試去連接服務(wù)端時(shí)排宰,你會(huì)在日志中看到如下的異常信息:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
服務(wù)端的日志信息通常會(huì)更加詳細(xì):
javax.net.ssl.SSLHandshakeException: no cipher suites in common
這意味著你已經(jīng)在服務(wù)端與客戶端配置了密碼套件似芝,但是它們各自密碼套件的交集為空。
解決辦法
檢查服務(wù)端與客戶端指定的 excludedCipherSuites 以及 includedCipherSuites 屬性的值板甘。