Harden remote port forwarding (tcpip-forward)#1059
Conversation
ejohnstown
commented
Jun 24, 2026
- Report allocated port in tcpip-forward reply (F-5573): Answer a port-0 (dynamic) tcpip-forward with the actually-bound port per RFC 4254 §7.1; callback returns >= WS_FWD_PORT_CHECK (1024) as the port, below it as a WS_FwdCbError status. A success that reports no port is undone and rejected (mapped to WS_RESOURCE_E so a no-reply request keeps the link).
- Gate forwarded-tcpip opens like direct-tcpip (F-6275): Both forwarding channel types now require a fwdCb and fail closed without one; a forwarded-tcpip open reaching a server is rejected as wrong-direction before any policy hook runs.
There was a problem hiding this comment.
Pull request overview
This PR hardens SSH TCP/IP remote port forwarding handling by making tcpip-forward replies RFC-compliant for port-0 (dynamic) requests and by tightening admission rules for forwarding-related channel opens.
Changes:
- Introduces a documented
WS_FWD_PORT_CHECKboundary and return-value convention for forwarding callbacks to report allocated ports for port-0 remote forwards. - Updates forwarding handling to (a) return the allocated port in
tcpip-forwardsuccess replies and (b) fail closed for forwarding channel types when no forwarding callback is registered. - Expands regression tests to cover dynamic-port replies, cleanup-on-reject behavior, and forwarded-tcpip wrong-direction rejection.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
wolfssh/ssh.h |
Defines and documents the callback return convention boundary (WS_FWD_PORT_CHECK). |
src/internal.c |
Implements dynamic-port reporting for tcpip-forward and tightens forwarding channel-open policy. |
tests/regress.c |
Adds regression tests for port-0 reply behavior and forwarded-tcpip gating. |
examples/echoserver/echoserver.c |
Updates forwarding example to report OS-allocated port for port-0 binds. |
ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/echoserver.c |
Same as above for ESP-IDF example. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
yosuke-wolfssl
left a comment
There was a problem hiding this comment.
It looks good to me.
Maybe we can move WS_FWD_PORT_CHECK out from WS_FwdCbError since it's not pure error code, but it's acceptable.
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #1059
Scan targets checked: wolfssh-bugs, wolfssh-src
Findings: 1
1 finding(s) posted as inline comments (see file-level comments below)
This review was generated automatically by Fenrir. Findings are non-blocking.
- Reply to a port-0 (dynamic) tcpip-forward with the bound port. - Add WS_FWD_PORT_CHECK (1024) as the status/port boundary in WS_FwdCbError. - Callback returns a WS_FwdCbError status below it, the port at or above it. - DoGlobalRequestFwd reports the port and rejects a port-0 setup with none. - Map a callback rejection to WS_RESOURCE_E so a no-reply request keeps the link. - Update the echoserver reference callbacks (examples and Espressif) to recover the OS-chosen port with getsockname() and return it under the new convention. - Add regress coverage for the allocated-port and rejection paths. Issue: F-5573 Co-authored-by: John Safranek <john@wolfssl.com>
- forwarded-tcpip was never gated; fell through to default-accept channelOpenCb. - Require fwdCb for both forwarding channel types, failing closed without it. - Reject server-side forwarded-tcpip opens before any policy hook runs. - Add regress coverage for both rejections. Issue: F-6275