|
ProtoCore v0.0.1
Deterministic, zero-heap network stack for embedded targets
|
Layer: L5 Session · Build flags: PC_ENABLE_SSH, PC_ENABLE_SSH_CLIENT
This is the mirror of the SSH server. Instead of accepting inbound SSH, the device is the SSH client: it dials OUT to a relay with a public address (any OpenSSH host), authenticates with its own ed25519 key, and asks the relay to forward a port back to it (tcpip-forward, RFC 4254 §7.1 - the ssh -R seam). A connection to the relay's forwarded port is tunnelled to a local service on the device. So a device on a home LAN, behind CGNAT, or inside a firewall stays reachable from anywhere - no public IP, no inbound port opened.
Here the local service is the device's own web server on :80. On the relay:
The handshake's field arithmetic runs in the caller's task and needs real stack: curve25519/ed25519 peak ~10.5 KB, and the ML-KEM hybrid (PC_ENABLE_PQC_KEX) ~16 KB. The Arduino loop() task's default 8 KB is not enough - create a dedicated task and drive begin()/poll() from it (a build guard enforces the matching worker-stack floor):
There is no trust-on-first-use. You supply host_pin = the SHA-256 of the relay's host-key blob, and the handshake aborts if the relay presents anything else. It is type-agnostic (works whether the relay's key is ed25519, ECDSA or RSA). Get it:
WIFI_SSID/WIFI_PASS, RELAY_HOST, RELAY_USER, and HOST_PIN.AUTH_SEED (the device's private ed25519 seed).ssh-ed25519 ... line to the relay's ~/.ssh/authorized_keys.curl the relay's forwarded port - you reach the device.The dialed-down channel count and client RX buffer keep this within the classic ESP32's ~122 KB internal DRAM (the reverse client holds a relay connection plus one bridge per channel); a PSRAM/large-SRAM board uses the roomier per-variant defaults from its board profile, and add -DPC_ENABLE_PQC_KEX=1 for the ML-KEM hybrid (run the tunnel task with a >= 20 KB stack, as above).
The client offers the full modern suite and interoperates with any current SSH server: KEX mlkem768x25519-sha256 (when PQC is built), curve25519-sha256, ecdh-sha2-nistp256, diffie-hellman-group14-sha256; host keys ed25519 / ECDSA / RSA (all pinned); ciphers chacha20-poly1305 / aes256-gcm / aes256-ctr. Forwarded connections are bridged through a channel pool (PC_SSH_CLIENT_MAX_CHANNELS), so concurrent requests each get a channel.
HW-verified against OpenSSH 10.0 on an ESP32-S3: handshake + ed25519 auth + tcpip-forward + the forwarded-tcpip bridge to :80, concurrent and rapid-sequential requests returning the device's response byte-for-byte.