標籤:Linux

使用 Cmder 直入 WSL

因為工作有 SSH 連線到遠端機器操作的習慣,在換了 Surface Book 2[1] 之後,也還是想要儘量保持這個習慣,一般來說我都是使用 PieTTY[2] 在進行 SSH 連線,不過對於行動裝置我通常會再搭配上 Mosh[3] 使用,可惜在 Windows 上面沒有原生的 Client 支援,於是我打算在 WSL[4] 裡面安裝 Mosh 來使用!

初始規劃

原本我是在找尋可用的 Mosh client,發現 MobaXterm 有支援 mosh,不過試用了一下之後發現他對於鍵盤的 ASCII Keycode 支援沒有很好,一些按鍵是送不出去的,於是就放棄了,打算改轉我在桌機上面的做法——開 Linux 虛擬機再用 PieTTY 連線進入。

不過虛擬機這個念頭很快就被 WSL 取代了(我 Hyper-V 都打開準備要裝系統了XD),因為筆電還是會想要以電量為優先考量,如果裝 VM 的話,電池很快就不夠力了……

於是這邊有兩個想法:

  1. 在 WSL 裡面啓用 SSH Server,用 PieTTY 搭配自動登入[5]來作為 mosh 的執行器
  2. 找一個 PieTTY 的替代品直接接入 WSL Shell 來執行 mosh

由於 WSL 的 lifecycle 只會到所有 shell 關閉就結束,所以如果要用方案 1 的話還必須在 Windows 裡面建立一個 service 來掛著 WSL sshd 的 Deamon(怎麼有種 Docker 的感覺XD),有點小麻煩,雖然我很喜歡,因為 PieTTY 已經用習慣了,其實我沒有很想換 Terminal…… 如果之後用的不順再來研究這個方法XD

使用 Cmder

不過介於我懶惰設定的關係,所以我姑且選擇了方案 2,我找了一個 Windows Terminal Emulator —— Cmder[6],他其實是把 ConEmu[7] 做了一些包裝,使用起來還算是上手,設定一下快捷鍵之後覺得應該還能接受

不過設定 WSL 的地方就需要照著說明來做了,原先我以為進去 cmder 之後,下 ubuntu 啓用 WSL 就完美了,結果在我 ssh/mosh 到遠端機器的時候發現 256 color 的設定不見了,整個顏色都變得很奇怪。

查了一下資料之後發現好像需要 wslbridge 來幫忙轉換一些畫面繪製的指令,這部份其實也不需要自己安裝額外的東西,cmder 包裝的 ConEmu 版本夠新,需要的元件其實本來就有包含了,我們只需要自己加上 Task config。

依照這篇的說明,首先建立一個 Task(名稱隨便取,像我就使用 wsl::bridge),在指令的部分填上如下內容:

set "PATH=%ConEmuBaseDirShort%\wsl;%PATH%" & %ConEmuBaseDirShort%\conemu-cyg-64.exe --wsl -cur_console:pnm:/mnt -t bash -l

然後在 cmder 建立新 Tab 的時候選擇這個 task,就可以得到一個有 256color support 的 Terminal 了!

看看全彩的 lolcat 就覺得……好空虛XDDD

預設進入 mosh

如果想要預設建立某個 mosh 連線的話,也可以複製剛剛的 Task,並在後面加上:-c "mosh [email protected]" 讓 bash 會自動執行 mosh 之後離開。


  1. Surface Book 2 開箱一文 ↩︎

  2. PieTTY ↩︎

  3. Mosh: the mobile shell ↩︎

  4. WSL: Windows Subsystem for Linux ↩︎

  5. 修改 PAM 讓特定 IP 透過 SSH 登入時不需要輸入密碼一文 ↩︎

  6. cmder | Console Emulator ↩︎

  7. ConEmu - Handy Windows Terminal ↩︎

修改 PAM 讓特定 IP 透過 SSH 登入時不需要輸入密碼

我有兩臺電腦,一臺是外出用的 MacBook Air (13" later)、另一臺是自己組裝的 Windows 桌機,但平時工作都是在 Windows 上面開 Linux(當然是我最愛的 Ubuntu)的 VM 再從兩臺電腦 SSH 進去 VM 裡面。但從 Windows SSH 進去 VM 的時候就很想跳過輸入密碼的步驟,當然用 SSH Key 也可以辦到,但我覺得他們根本就是同一個電腦啊,還要加上 SSH Key 也太累了吧!要如何僅依靠來源 IP 就決定要不要輸入密碼呢?

!!警告!! 跳過密碼就可以登入是非常危險的,看看蘋果今天才緊急更新的免密碼登入 root 漏洞,即使是本機也是非常危險的呢!
https://support.apple.com/en-us/HT208315

PAM (Pluggable Authentication Modules)

首先,想跟各位介紹一個叫做 PAM (Pluggable Authentication Modules) 的模組,PAM 提供了一套驗證的 API 讓應用程式可以透過 PAM 做使用者驗證。

我們即是要對 PAM 來下手,而 PAM 的設定檔們都存放在 /etc/pam.d/ 下,sshd 會有自己專屬的設定檔可以使用就叫做 /etc/pam.d/sshd

我們把設定檔 cat 出來看一下會看到類似以下的內容:

# PAM configuration for the Secure Shell service

# Standard Un*x authentication.
@include common-auth

# Disallow non-root logins when /etc/nologin exists.
account    required     pam_nologin.so

# Uncomment and edit /etc/security/access.conf if you need to set complex
# access limits that are hard to express in sshd_config.
# account  required     pam_access.so

# Standard Un*x authorization.
@include common-account

# SELinux needs to be the first session rule.  This ensures that any
# lingering context has been cleared.  Without this it is possible that a
# module could execute code in the wrong domain.
session [success=ok ignore=ignore module_unknown=ignore default=bad]        pam_selinux.so close

# Set the loginuid process attribute.
session    required     pam_loginuid.so

# Create a new session keyring.
session    optional     pam_keyinit.so force revoke

# Standard Un*x session setup and teardown.
@include common-session

# Print the message of the day upon successful login.
# This includes a dynamically generated part from /run/motd.dynamic
# and a static (admin-editable) part from /etc/motd.
session    optional     pam_motd.so  motd=/run/motd.dynamic
session    optional     pam_motd.so noupdate

# ......

# Standard Un*x password updating.
@include common-password

我們可以很清楚的看到,每一條項目都有以下格式:

[驗證類別] [控制標記] [檔名] [參數]

驗證類別 (Type)

驗證類別分成四種:account(帳號)、auth(驗證)、session(執行期間)、password(更新驗證資訊)。

舉例來說,我們可以清楚的看到 account 中有一個用來阻擋 nologin 的模組:

# Disallow non-root logins when /etc/nologin exists.
account    required     pam_nologin.so

表示這個模組會在使用者登入時,輸入帳號後,檢查是否為 nologin,來決定這個帳號是否合法。

控制標記 (Control Flag)

常見的控制標記有 4 種:

  • required
    若驗證成功則帶有 success 的標誌;
    若驗證失敗則帶有 failure 的標誌。
    但不論成功或失敗都會繼續後續的驗證流程。

  • requisite
    若驗證失敗則立刻回報 failure,並終止後續的驗證流程;
    若驗證成功則帶有 success 的標誌並繼續後續的驗證流程。
    required 最大的差異就在於失敗時就會終止驗證流程。

  • sufficient
    若驗證成功則立刻回報 success,並終止後續的驗證流程;
    若驗證失敗則帶有 failure 標誌並繼續後續的驗證流程。
    requisits 剛好相反。

  • optional
    不論成功或失敗都不回報且不影響後續的流程。

但這些都只是常見的預設標記,PAM 還提供了自己撰寫驗證流程規則的標記,可以自己寫要不要回報,以及要不要中斷流程。可以看看 pam.d(5) 的 man page。

觀察可用的 PAM 模組

我們可以注意到預設的 sshd 裡面有一個令人有興趣的設定是:

# Uncomment and edit /etc/security/access.conf if you need to set complex
# access limits that are hard to express in sshd_config.
# account  required     pam_access.so

如果我把註解拿掉的話,他就會在帳號檢查階段(account),去檢查這個帳號是不是可以被存取,這個不是跟我們想要的東西很像嗎?
只是我們要檢查的是「這個密碼需不需要被輸入」而已,很像嘛! (迷之音:真的很像嗎?)

實做

PAM 設定

以下是我使用的設定,插在 common-auth 之前,來保持我的語句比其他人早驗證:

# PAM configuration for the Secure Shell service

auth [success=done default=ignore] pam_access.so accessfile=/etc/security/sshd-access-local.conf # <<<<<<<
# Standard Un*x authentication.
@include common-auth

# ...

我在這裡使用了 auth,讓我需要被驗證的時候執行檢查;
而在控制標記的部分我則是自己撰寫了規則 [success=done default=ignore],表示在 success 的時候就直接回報 success 並結束驗證流程,但在非 success 的情況下就不回報也不結束流程(ignore)。
而使用的當然是剛剛觀察到的 pam_access.so 模組,他可以接受一個名為 accessfile 的參數,來提供他判斷的條件,這裡我先命名為 /etc/security/access-local.conf
其他參數大家可以參考 pam_access(8) 的 man page。

pam_access.so accessfile

接下來我們來看看這個 accessfile 裡面到底長怎樣,一樣大家可以參考 access.conf(5) 的 man page,先列出我自己的 config:

+ : davy : 192.168.3.0/24
+ : davy : 10.8.0.0/24
- : ALL : ALL

相對於 PAM 的設定,access.conf 的格式更加地簡單了:

permission : users/groups : origins

其中 permission 只有兩種值: +- 分別對應到 granteddenied,表示符合條件的狀況會不會通過測驗;
user/groups 則是指定套用規則的使用者或群組,可以用 ALL 表示全部使用者皆套用;
origins 指定的是來源,可以是 TTY 名稱、IP address、domain name 等,其中有兩個特別的值是 ALLLOCAL,分別表示全部適用以及套用到本機服務或本機 TTY。

設定檔前兩條規則,帳號都限定在我個人的帳號(davy);
而第一條是只有我才連得上的 VPN subnet、第二條是 VM 網路的 subnet。
最後還要加上一條 deny 全部其他的規則,到這裡我們已經大功告成了。

測試

只要我從符合上述條件的網路登入指定帳號,就可以不需要密碼就能夠登入了!

以下是從 Windows 用 pietty 登入的測試結果,可以看到我輸入完帳號之後就進入系統了:

最後我在這裡還是要在提醒大家一次:跳過密碼就可以登入是非常危險的,除非你的環境十分值得信賴,不然千萬不要忽略驗證!