18 KiB
Kylin Remote Control & Monitoring Setup
Complete reference for controlling and monitoring a Kylin Linux machine from a Windows 11 PC over a local phone-hotspot network. No VPN is used for the SSH connection itself — only the local Wi-Fi/hotspot.
0. Bootstrap — START HERE in a new session
The connection is already fully set up (SSH key login + passwordless sudo). A new session does NOT need to repeat the setup in §2–§3 — those sections are records of what was already done. Just connect and go.
Verify everything with one command (run from the Windows machine, e.g. Claude Code's Bash tool):
ssh -o BatchMode=yes -o ConnectTimeout=10 kylin 'echo SSH_OK; whoami; hostname; sudo -n true && echo SUDO_OK'
Expected: SSH_OK / caichl / caichl-HUAWEIQINGYUNL420 / SUDO_OK.
- ✅
SSH_OK+SUDO_OK→ full control. Run anything (incl.sudo) viassh -o BatchMode=yes kylin "<command>". No password needed. - ❌ asks for password / times out → most likely the hotspot IP changed
(
192.168.43.248is DHCP-assigned and can change between sessions). Ask the user to re-check the Kylin IP (hostname -Ion that machine), updateC:\Users\adusu\.ssh\config, then re-verify. If it asks for a password, the key may have been removed — see §2.3 / §2.4 to re-establish. - ℹ️ SSH prints a harmless post-quantum warning to stderr — ignore it (the examples in this doc filter it out).
Connect manually: ssh kylin (alias in C:\Users\adusu\.ssh\config → caichl@192.168.43.248,
with the pinned cipher/MAC already configured — see §2).
A fresh Claude Code session also auto-loads memory pointers (
MEMORY.md→kylin-remote-machine,kylin-command-logging,kylin-mihomo-vpn) that link back here. This file is the authoritative, self-contained reference.
1. The two machines
| Role | Details |
|---|---|
| Controller | Windows 11 (C:\Users\adusu), where Claude Code + VPN run |
| Target | Kylin V10 SP1, Huawei QINGYUN L420, ARM64 / aarch64 |
| Network | Shared phone hotspot, subnet 192.168.43.x |
| Target IP | 192.168.43.248 |
| Target user | caichl |
Key idea: Claude Code needs the VPN to reach Anthropic's servers, but the SSH hop from Windows → Kylin is local LAN traffic and needs no VPN. The two connections are independent.
2. SSH connection
2.1 Required cipher/MAC (important)
The default cipher fails over this hotspot link with
Corrupted MAC on input. The connection must pin a specific cipher and MAC:
-c aes256-ctr -m hmac-sha2-256
2.2 Windows SSH config
File: C:\Users\adusu\.ssh\config
Host kylin kyln
HostName 192.168.43.248
User caichl
Ciphers aes256-ctr
MACs hmac-sha2-256
With this in place, simply run:
ssh kylin # or: ssh kyln (both aliases work)
The equivalent explicit command (no config) is:
ssh -m hmac-sha2-256 -c aes256-ctr caichl@192.168.43.248
2.3 Passwordless login (SSH key)
The Windows key ~/.ssh/id_ed25519.pub was copied to the Kylin machine:
Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub | `
ssh kylin "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
Result: ssh kylin logs in with no password.
2.4 Passwordless sudo
So admin commands can run non-interactively from Windows:
# Run once on the Kylin machine (asks for password the one time)
sudo bash -c 'echo "caichl ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/caichl-nopasswd; \
chmod 440 /etc/sudoers.d/caichl-nopasswd; \
visudo -cf /etc/sudoers.d/caichl-nopasswd'
Security note: This makes
caichla passwordless-sudo account — acceptable for a disposable machine only. To revert:sudo rm /etc/sudoers.d/caichl-nopasswd.
After this, from Windows you can run, e.g.:
ssh -o BatchMode=yes kylin "sudo systemctl status ssh"
2.5 Account credentials (recovery only)
⚠️ Plaintext password below — keep this file private; do NOT commit or share it.
| Item | Value |
|---|---|
| User | caichl |
| Password | Caicai@2026 |
Normally not needed — SSH login uses the key (§2.3) and sudo is passwordless
(§2.4). Use this only to recover if the key auth or sudoers drop-in is ever lost
(e.g. to log in interactively and re-copy the key, or to re-create
/etc/sudoers.d/caichl-nopasswd). To change it: run passwd on the Kylin machine.
3. Initial SSH server setup (done on the Kylin machine)
sudo apt update
sudo apt install -y openssh-server
sudo systemctl enable --now ssh
hostname -I # find the IP (192.168.43.248)
whoami # confirm the username (caichl)
4. Monitoring
4.1 SSH logins & sessions (works out of the box)
who # who is logged in + source
w # sessions + current command
last # login history with IPs
lastb # FAILED login attempts (sudo)
sudo grep "Accepted" /var/log/auth.log # successful SSH logins
sudo grep "Failed" /var/log/auth.log # failed/suspicious attempts
sudo tail -f /var/log/auth.log # live SSH activity
4.2 Command logging — no reboot (WORKING)
Logs every command typed in an interactive shell, with user, tty, source IP, and the command text.
/etc/profile.d/cmdlog.sh
# Log interactive shell commands to syslog (facility local6) -> /var/log/cmdlog.log
if [ -n "$BASH" ] && [ -n "$PS1" ]; then
export PROMPT_COMMAND='logger -p local6.notice -t cmdlog "user=$USER tty=$(tty 2>/dev/null) from=$(who am i 2>/dev/null | sed -n "s/.*(\(.*\)).*/\1/p") cmd=$(history 1 | sed "s/^ *[0-9]* *//")"'
fi
/etc/rsyslog.d/30-cmdlog.conf
local6.* /var/log/cmdlog.log
Setup commands
sudo touch /var/log/cmdlog.log
sudo chown syslog:adm /var/log/cmdlog.log # MUST be syslog-owned (rsyslog drops privs)
sudo chmod 640 /var/log/cmdlog.log
sudo systemctl restart rsyslog
View the logs
sudo cat /var/log/cmdlog.log # all logged commands
sudo tail -f /var/log/cmdlog.log # live
Example line:
Jun 11 10:54:22 caichl-HUAWEIQINGYUNL420 cmdlog: user=caichl tty=/dev/pts/5 from=192.168.43.180 cmd=echo hello
Gotcha: rsyslog runs as the
sysloguser. If/var/log/cmdlog.logis owned byroot:root, nothing is written. It must bechown syslog:adm.
4.3 System-wide auditing — auditd (QUEUED, UNVERIFIED)
auditd is installed and enabled, with a rule logging all execve for real
users:
/etc/audit/rules.d/cmdlog.rules
-a exit,always -F arch=b64 -S execve -F auid>=1000 -F auid!=4294967295 -k cmdlog
It cannot run yet because the kernel booted with audit=0. This was changed to
audit=1:
sudo sed -i 's/audit=0/audit=1/' /etc/default/grub
# /boot is read-only on this device — remount to rebuild grub
sudo mount -o remount,rw /boot
sudo update-grub
sudo mount -o remount,ro /boot
Caveat: This device appears to boot via Huawei firmware, not standard GRUB (running kernel
-27is not the one ingrub.cfgwhich lists-11, and the kernel cmdline has Huawei-specific params). So theaudit=1change may not take effect on reboot. The no-reboot logging in §4.2 already covers interactive command logging, so auditd is a bonus.
Verify after any reboot
cat /proc/sys/kernel/audit_enabled # want: 1
sudo systemctl is-active auditd # want: active
sudo ausearch -k cmdlog -i | tail -40 # human-readable command audit
sudo aureport -x --summary # summary of executables run
5. Device-specific quirks (Huawei Kylin ARM64)
- Architecture is ARM64 (aarch64). Software must have an ARM64 build; x86-only proprietary apps will not install/run.
/bootis a separate ext4 partition mounted read-only. Remount rw to change GRUB, then back to ro (see §4.3).- Boot likely controlled by Huawei firmware, limiting effectiveness of GRUB cmdline edits.
- Hotspot link needs
aes256-ctr/hmac-sha2-256or SSH fails with "Corrupted MAC on input".
6. Quick reference
# Connect
ssh kylin
# Run a one-off command from Windows
ssh kylin "uptime"
# Run an admin command from Windows
ssh kylin "sudo systemctl status ssh"
# See logged commands
ssh kylin "sudo tail -50 /var/log/cmdlog.log"
# Watch live
ssh kylin "sudo tail -f /var/log/cmdlog.log"
# SSH login history
ssh kylin "last"
7. Troubleshooting
| Symptom | Cause / Fix |
|---|---|
Corrupted MAC on input |
Use -c aes256-ctr -m hmac-sha2-256 (already in config) |
Connection timed out |
Both devices not on same hotspot, or AP/client isolation on the phone — disable isolation |
ssh kyln "could not resolve" |
Alias spelling — config now accepts both kylin and kyln |
| Still asks for password | SSH key not copied (§2.3) |
sudo asks for password |
sudoers drop-in empty/missing (§2.4) |
audit support not in kernel |
Kernel booted audit=0; needs reboot with audit=1 (§4.3) |
cmdlog.log empty |
File not owned by syslog:adm; sudo chown syslog:adm /var/log/cmdlog.log then restart rsyslog |
grub.cfg: Read-only file system |
/boot is read-only; sudo mount -o remount,rw /boot first |
VPN GUI app won't run (GLIBC_2.34 not found) |
Kylin has glibc 2.31; modern Flutter/Electron clients need 2.34+. Use the Go-based mihomo core instead (see §8) |
8. VPN / proxy: mihomo + web dashboard
Why not FlClash / GUI clients: Kylin V10 SP1 has glibc 2.31, but FlClash 0.8.93 and similar modern GUI clients require glibc 2.34+ and fail to run. Upgrading glibc would risk breaking the OS. mihomo is a statically-linked Go binary with no glibc dependency, so it runs fine — controlled via a browser dashboard.
Current state
VPN is currently OFF. The
mihomoservice is stopped and disabled (auto-start removed), so it stays off across reboots until re-enabled. Ports7890/9090are closed. The full configuration below is intact and ready to resume.
Turn the VPN on / off (run on Kylin, or via ssh kylin)
# TURN ON (and restore auto-start on boot)
sudo systemctl enable --now mihomo
# TURN OFF for this session only (comes back on next reboot)
sudo systemctl stop mihomo
# TURN OFF and keep it off across reboots <-- current state
sudo systemctl stop mihomo && sudo systemctl disable mihomo
# Check state
systemctl is-active mihomo # active / inactive
systemctl is-enabled mihomo # enabled / disabled
Reminder: if you had set the Kylin system proxy to
127.0.0.1:7890, switch it back to "None" while the VPN is off, or apps will fail to reach the network.
Desktop access
A launcher "Mihomo VPN Dashboard" was added to the app menu (Network category)
at /usr/share/applications/mihomo-dashboard.desktop; it opens
http://127.0.0.1:9090/ui/. (Only works while the service is running.)
Installed components
| Item | Location / value |
|---|---|
| mihomo core | /usr/local/bin/mihomo (Clash.Meta v1.19.27, arm64) |
| Config | /etc/mihomo/config.yaml |
| Web dashboard (zashboard) | /etc/mihomo/ui/ |
| systemd service | /etc/systemd/system/mihomo.service (auto-starts on boot) |
| Proxy port (HTTP+SOCKS) | 7890 |
| Dashboard API | 0.0.0.0:9090 |
| Dashboard secret | 428968aebf7c301565c6b6d3a11826c4 |
Install steps (done; for reference / rebuild)
# binary (downloaded on Windows through VPN, scp'd over to dodge chicken-and-egg)
gunzip mihomo-linux-arm64-vX.gz
sudo install -m 755 mihomo-linux-arm64 /usr/local/bin/mihomo
# dashboard
sudo mkdir -p /etc/mihomo/ui && sudo unzip zashboard-dist.zip -d /etc/mihomo/ui
# config.yaml: mixed-port 7890, external-controller 0.0.0.0:9090, secret, external-ui: ui,
# proxy-providers (subscription URL), PROXY (select) + AUTO (url-test) groups
sudo systemctl enable --now mihomo
The subscription URL lives in
/etc/mihomo/config.yamlunderproxy-providers:.external-ui-namemust NOT be set (it makes mihomo look in aui/<name>subdir and auto-download); serve/etc/mihomo/uidirectly.
Open the dashboard
- From Windows browser:
http://192.168.43.248:9090/ui/- backend/API:
http://192.168.43.248:9090• secret:428968aebf7c301565c6b6d3a11826c4
- backend/API:
- From Kylin desktop browser:
http://127.0.0.1:9090/ui/
Use the proxy
Point apps at 127.0.0.1:7890 (HTTP/SOCKS), or set the Kylin system proxy
(Settings → Network → Proxy → Manual → 127.0.0.1:7890). For transparent
whole-system routing, enable mihomo TUN mode (/dev/net/tun is present).
Manage via API (examples)
S=428968aebf7c301565c6b6d3a11826c4
# switch PROXY group to a node / AUTO
curl -X PUT -H "Authorization: Bearer $S" http://127.0.0.1:9090/proxies/PROXY -d '{"name":"AUTO"}'
# verify exit IP goes through the proxy
curl -x http://127.0.0.1:7890 -s https://api.ip.sb/geoip
# update subscription / reload
sudo systemctl restart mihomo
Verified working: exit IP resolved to Singapore and google.com/generate_204
returned HTTP 204 through the proxy.
9. Browsers
| Browser | App-menu name | Type / location | Notes |
|---|---|---|---|
| Chromium | "Chromium" | snap chromium v149 (/snap/bin/chromium) |
Installed as the Chrome/Edge equivalent — same engine, Chrome Web Store extensions work. Set as the default browser. |
- Chrome & Edge cannot be installed — neither has an official ARM64 Linux build (same architecture wall as the VPN GUI clients). Chromium is the substitute.
- Installing the chromium snap first required updating snapd (Kylin shipped 2.54,
too old → error
assumes unsupported features: snapd2.55). Fix:sudo snap install snapd(brought it to 2.75.2), thensudo snap install chromium. - Default browser is recorded in
~/.config/mimeapps.list(text/html,x-scheme-handler/http(s)→chromium_chromium.desktop). If a double-click opens the wrong app, right-click the file → Open with → Chromium → Set as default.
Desktop instruction files (for the user at the machine)
~/桌面/VPN_Guide.html+~/桌面/VPN_Guide.md(copies also in~/Desktop/): a user-facing "how to turn the VPN on/off" guide. Double-click the.htmlto read it rendered in a browser; the.mdopens in VS Code (code, installed) withCtrl+Shift+Vpreview.- App-menu launcher "Mihomo VPN Dashboard" → opens
http://127.0.0.1:9090/ui/(only works while the mihomo service is running).
10. Inventory — everything set up on the Kylin machine
| Area | What | State |
|---|---|---|
| Access | SSH alias kylin/kyln, key login, passwordless sudo |
✅ active |
| Monitoring | SSH login logs (auth.log); command logging → /var/log/cmdlog.log |
✅ active |
| Monitoring | auditd execve rule | ⏳ queued (needs reboot + audit=1; may not take on Huawei firmware) |
| VPN | mihomo core + zashboard dashboard, subscription configured | ⛔ installed, OFF (stopped + disabled) |
| Browser | Chromium v149 (default), 360/CNOOC browser | ✅ installed |
| Editors | VS Code (code), pluma, WPS Office |
✅ pre-installed |
| IDE | Cursor 3.7.27 (/opt/cursor) via env -i wrapper |
✅ installed (see §11) |
| Desktop docs | VPN_Guide.html / .md, dashboard launcher |
✅ on desktop |
11. Cursor IDE (Electron) — install + crash fixes
Cursor (AI code editor, Electron-based) installed as an extracted AppImage at
/opt/cursor (currently v3.7.27, ARM64). It will NOT run with a normal launcher
on this Huawei/Kylin box — it needs a special wrapper.
Why the special launcher (three Kylin/Huawei ARM64 problems)
- EFAULT machine-ID probe crash — Cursor runs a command to generate a unique
machine ID; the Kylin kernel blocks that memory
writeas suspicious →Error: EFAULT: bad address in system call argument, write→ instant crash. Fix:env -istrips the environment (especially D-Bus) so Cursor skips the probe. - Mali GPU crash (段错误 / segfault) — hardware rendering conflicts with Huawei's
Mali GPU driver (
dmesg:mali gpu: kctx ... create/destroyedat crash time). Fix:--disable-gpu(software rendering). - Blocked sandbox —
--no-sandbox. Also installedxdg-desktop-portal+xdg-desktop-portal-gtk(1.6.0) for the Wayland file picker (necessary but not sufficient alone).
The launcher (already installed)
- Wrapper:
/usr/local/bin/cursor-launch - Start-menu entry:
/usr/share/applications/cursor.desktop→Exec=/usr/local/bin/cursor-launch %F
#!/bin/sh
exec env -i \
HOME="$HOME" DISPLAY="${DISPLAY:-:0}" PATH="$PATH" \
/opt/cursor/usr/share/cursor/cursor --no-sandbox --disable-gpu "$@"
Updating Cursor to a newer version
- Get the latest ARM64 AppImage URL (downloads on Windows through the VPN):
curl -sL -A "Mozilla/5.0" -H "Accept: application/json" \ "https://www.cursor.com/api/download?platform=linux-arm64&releaseTrack=stable" # -> JSON with "downloadUrl" (…/Cursor-X.Y.Z-aarch64.AppImage) and "version" curl -L -C - -o Cursor-new.AppImage "<downloadUrl>" scpit to Kylin, then:chmod +x Cursor-new.AppImage cd /tmp && ./Cursor-new.AppImage --appimage-extract # -> /tmp/squashfs-root sudo rm -rf /opt/cursor && sudo cp -r /tmp/squashfs-root /opt/cursor sudo chown -R root:root /opt/cursor && rm -rf /tmp/squashfs-root- No change needed to the wrapper or menu entry — paths stay the same.
Verify glibc first (must need ≤ 2.31):
objdump -T /opt/cursor/usr/share/cursor/cursor | grep -oE 'GLIBC_[0-9.]+' | sort -V | tail.
Cleanup note
Old AppImages in ~/software/ (Cursor-3.2.11, Cursor-3.7.27) and the user's
manual extract ~/software/squashfs-root (3.2.11) are redundant now that /opt/cursor
is the install — safe to delete to reclaim space.