Lifecycle, Security, and Troubleshooting
SshTunnel is controlled by the application thread but performs its ongoing listening and data movement in Chilkat-managed background threads. Correct shutdown and targeted logging are important because starting, accepting, and relaying are not all performed by the method-calling thread.
The lifecycle methods affect different thread groups. All thread groups shown are internal to the application process.
Chilkat object or managed thread
Separate process or application code
SSH server or remote network component
Destination service
Local-computer boundary
Start and verify the listener
BeginAccepting(listenPort) starts a background thread that creates the listening socket, binds it, and begins accepting. The initial method can return before a later bind failure is visible. After allowing the listener thread to start, check IsAccepting. If port 0 was requested, read the actual operating-system-assigned port from ListenPort.
Shutdown methods affect different scopes
| Method | What it stops | What remains |
|---|---|---|
StopAccepting(waitForThread) | The listener background thread; no new local clients are accepted. | Existing client connections and the SSH tunnel can continue. |
DisconnectAllClients(waitForThreads) | All active client connections and their client threads. | The SSH tunnel remains open and accepting can continue or be restarted. |
CloseTunnel(waitForThreads) | The SSH tunnel and all existing clients; optionally waits for tunnel and client threads to exit. | Nothing should be expected to remain usable. |
Recommended orderly shutdown
// Prevent new clients. tunnel.StopAccepting(true) // End existing client sessions if they are not allowed to drain naturally. tunnel.DisconnectAllClients(true) // Final SSH and thread shutdown. tunnel.CloseTunnel(true)
State and diagnostics
| Member | Use |
|---|---|
IsAccepting | Confirms whether the listener background thread is active. |
ListenPort | Reports the requested listener port or the allocated port when BeginAccepting(0) was used. |
IsSshConnected() | Reports whether the SSH connection still exists. |
GetCurrentState() | Returns XML describing current tunnels, channels, and clients. |
LastErrorText | Provides detailed diagnostics for the most recent method or property operation. |
Logs correspond to different background activity
| Log | Thread or activity |
|---|---|
KeepAcceptLog, AcceptLog, AcceptLogPath | The listener thread that binds and accepts local connections. |
KeepTunnelLog, TunnelLog, TunnelLogPath | The SSH tunnel thread and channel-management activity. |
ClientLogDir | Creates a separate log file for each accepted tunnel client. |
Security checklist
- Compare
HostKeyFingerprintwith a trusted expected fingerprint after connecting and before sending credentials. - Use
ListenBindIpAddress = "127.0.0.1"when only applications on the same computer should use the tunnel. - Protect private keys, SSH passwords, proxy passwords, and inbound SOCKS passwords.
EnableSecretscan allow supported credential values to be resolved from secure operating-system storage. - Remember that the SSH-server-to-destination connection is not protected by the tunnel after it leaves the SSH server.
- Do not expose a dynamic SOCKS listener without deliberate access controls.
Troubleshooting by symptom
| Symptom | First checks |
|---|---|
Connect fails | LastErrorText, SSH hostname and port, outbound proxy settings, firewall rules, and ConnectTimeoutMs. |
| SSH connects but authentication fails | Correct SSH username, selected authentication method, private key, password, and server policy. |
BeginAccepting appears successful but clients cannot connect | Check IsAccepting, AcceptLog, whether the port was already in use, and ListenBindIpAddress. |
| Local connection succeeds but destination fails | For static forwarding, check DestHostname, DestPort, TunnelLog, and reachability from the SSH server's network. |
| Dynamic client cannot connect | Check InboundSocksVersion, client SOCKS configuration, inbound credentials, and whether the destination is allowed by the SSH server. |
| Need to see active channels and clients | Call GetCurrentState() and inspect the returned XML. |