ssh-workbench/docs/SOCKS5_TEST.md
jima 902ff21417 Session navigation: top bar tabs + side drawer, SFTP stub, SOCKS5 test docs
Dual-mode session navigation for TerminalActivity:
- Top bar mode: 36dp tab strip with scrollable session tabs (teal accent),
  SFTP tab (amber), + popup menu (New session / Open SFTP / Switch to drawer)
- Drawer mode: 260dp left DrawerLayout with session list (teal dot indicators),
  SFTP section, hamburger button on quick bar, footer to switch back
- In-session switching via popup/drawer footer; global default in Settings
- Session switching rebinds TerminalSurfaceView.screenBuffer to target session

New files:
- TerminalSessionNav.kt — tab bar, drawer, session switching, hamburger button
- SftpActivity.kt — stub ("SFTP — coming soon"), registered in manifest
- SessionNavTest.kt — 8 unit tests for NavMode enum and label truncation

Settings:
- Session navigation preference (Top bar / Drawer) in Appearance section
- Show session tab bar toggle (when top bar mode selected)
- sessionNavStyle + showSessionTabBar in TerminalPreferences + SettingsViewModel

Also: rewrote docs/SOCKS5_TEST.md to use adb forward from dev machine

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 17:27:50 +01:00

4.7 KiB

SOCKS5 Dynamic Port Forwarding — Manual Test Guide

All tests run from your dev machine terminal, not from adb shell. The SOCKS5 proxy listens on the Android device's loopback; adb forward bridges it to your machine's loopback so standard tools (curl, browsers) work directly.


Prerequisites

  1. SSH Workbench installed on the device (debug build).
  2. A saved SSH connection with a DYNAMIC port forward:
    • Type: Dynamic (SOCKS5)
    • Local port: 1080
    • Bind address: 127.0.0.1
  3. Open the connection in the app — the terminal should be live.
  4. Bridge the port to your dev machine (once per ADB session):
adb forward tcp:1080 tcp:1080
  1. Verify the forward is active:
adb forward --list

Expected output includes a line like:

22160523026079 tcp:1080 tcp:1080

If it shows nothing, the forward wasn't set up — re-run step 4.

You can also confirm the proxy is listening on-device:

adb shell netstat -tlnp | grep 1080

Should show LISTEN on 127.0.0.1:1080.


Test 1: Basic HTTP

curl --socks5-hostname 127.0.0.1:1080 http://example.com

Expected: HTML content from example.com.

Failure: curl: (7) Failed to connect to 127.0.0.1 port 1080 means either the app isn't connected, the DYNAMIC forward isn't configured, or adb forward wasn't run. Check the terminal for a red "Port forward failed" banner.


Test 2: HTTPS — verify tunnel routing

curl --socks5-hostname 127.0.0.1:1080 https://httpbin.org/ip

Expected: JSON showing the SSH server's public IP, not your dev machine's IP. This confirms traffic is routed through the SSH tunnel, not sent directly.


Test 3: DNS-through-tunnel

The --socks5-hostname flag sends the domain name to the SOCKS5 proxy, which resolves it on the SSH server side. This avoids DNS leaks.

# DNS resolved on the SSH server (no local DNS leak):
curl --socks5-hostname 127.0.0.1:1080 https://example.com

# For comparison — DNS resolved locally, only TCP tunneled:
curl --socks5 127.0.0.1:1080 https://example.com

Both should succeed. Use --socks5-hostname in production to prevent DNS leaks.


Test 4: Concurrent connections

Browsers open 6+ parallel connections. Verify the proxy handles them:

curl --socks5-hostname 127.0.0.1:1080 http://example.com &
curl --socks5-hostname 127.0.0.1:1080 https://httpbin.org/ip &
wait

Expected: Both complete without either one hanging. If the second request blocks until the first finishes, the proxy has a concurrency bug.


Test 5: RFC 1929 username/password auth

Some clients (Proxifier, strict browsers) require SOCKS5 username/password auth. The proxy accepts any credentials — the SSH session is the real auth boundary.

curl --socks5-hostname --proxy-user anyuser:anypass 127.0.0.1:1080 https://example.com

Expected: Same HTML as Test 1. The credentials are accepted and ignored.

Failure: curl: (97) Can't complete SOCKS5 connection means RFC 1929 negotiation is broken.


Test 6: Connection refused error

Request a port that nothing is listening on (on the SSH server's side):

curl --socks5-hostname 127.0.0.1:1080 http://127.0.0.1:9999

Expected: curl reports an error (SOCKS5 reply code 0x05 — connection refused). The SSH session should remain active and usable for subsequent requests.


Test 7: Unknown host error

Request a domain that doesn't resolve:

curl --socks5-hostname 127.0.0.1:1080 http://thishostdoesnotexist.invalid

Expected: curl reports an error (SOCKS5 reply code 0x04 — host unreachable). The SSH session should remain active.


Cleanup

Remove the ADB port forward when done testing:

adb forward --remove tcp:1080

Verify it's gone:

adb forward --list

Teardown note

Disconnecting the SSH session in the app closes the SOCKS5 proxy's ServerSocket. After disconnect, adb forward still exists but curl will get "Connection refused" because there's nothing listening on port 1080 on the device anymore. Run adb forward --remove tcp:1080 to clean up the stale forward.


Troubleshooting

Symptom Likely cause
Failed to connect to 127.0.0.1 port 1080 adb forward not set, or app not connected
Connection refused after successful setup SSH session disconnected — proxy closed
Second request hangs until first completes Sequential accept loop — concurrency bug
Can't complete SOCKS5 connection with --proxy-user RFC 1929 auth negotiation broken
Truncated downloads Half-close not implemented correctly
Slow throughput Relay buffer too small (should be 64 KB)