Example of use of direct port forwarding:
Mail client application Google Mail | ^ 5555 (arbitrary) | | 143 (IMAP2) V | SSH client =====> SSH server Legend: --P-->: port connexion through port P =====>: SSH tunnel
Example of use of reverse port forwarding:
Local mail server Mail client application ^ | | 5555 (arbitrary) 143 (IMAP2) | | V SSH client <===== SSH server Legend: --P-->: port connexion through port P =====>: SSH tunnel
Example of use of X11 tunnels:
Local display Graphical application (X11 server) (X11 client) ^ | | V SSH client <===== SSH server Legend: ----->: X11 connection through X11 display number =====>: SSH tunnel
How to establish X11 tunnels with libssh has already been described in this tutorial.
If you don't plan to forward the data you will receive to any local port, just put fake values like "localhost" and 5555 as your local host and port.
The example below shows how to open a direct channel that would be used to retrieve google's home page from the remote SSH server.
int direct_forwarding(ssh_session session) { ssh_channel forwarding_channel; int rc; char *http_get = "GET / HTTP/1.1\nHost: www.google.com\n\n"; int nbytes, nwritten; forwarding_channel = ssh_channel_new(session); if (rc != SSH_OK) return rc; rc = channel_open_forward(forwarding_channel, "www.google.com", 80, "localhost", 5555); if (rc != SSH_OK) { ssh_channel_free(forwarding_channel); return rc; } nbytes = strlen(http_get); nwritten = channel_write(forwarding_channel, http_get, nbytes); if (nbytes != nwritten) { ssh_channel_free(forwarding_channel); return SSH_ERROR; } ... ssh_channel_free(forwarding_channel); return SSH_OK; }
The data sent by Google can be retrieved for example with ssh_select() and ssh_channel_read(). Goggle's home page can then be displayed on the local SSH client, saved into a local file, made available on a local port, or whatever use you have for it.
When you call ssh_channel_forward_listen(), you can let the remote server chose the non-priviledged port it should listen to. Otherwise, you can chose your own priviledged or non-priviledged port. Beware that you should have administrative priviledges on the remote server to open a priviledged port (port number < 1024).
Below is an example of a very rough web server waiting for connections on port 8080 of remote SSH server. The incoming connections are passed to the local libssh application, which handles them:
int web_server(ssh_session session) { int rc; ssh_channel channel; char buffer[256]; int nbytes, nwritten; char *helloworld = "" "HTTP/1.1 200 OK\n" "Content-Type: text/html\n" "Content-Length: 113\n" "\n" "<html>\n" " <head>\n" " <title>Hello, World!</title>\n" " </head>\n" " <body>\n" " <h1>Hello, World!</h1>\n" " </body>\n" "</html>\n"; rc = ssh_channel_forward_listen(session, NULL, 8080, NULL); if (rc != SSH_OK) { fprintf(stderr, "Error opening remote port: %s\n", ssh_get_error(session)); return rc; } channel = ssh_channel_forward_accept(session, 60000); if (channel == NULL) { fprintf(stderr, "Error waiting for incoming connection: %s\n", ssh_get_error(session)); return SSH_ERROR; } while (1) { nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); if (nbytes < 0) { fprintf(stderr, "Error reading incoming data: %s\n", ssh_get_error(session)); ssh_channel_send_eof(channel); ssh_channel_free(channel); return SSH_ERROR; } if (strncmp(buffer, "GET /", 5)) continue; nbytes = strlen(helloworld); nwritten = ssh_channel_write(channel, helloworld, nbytes); if (nwritten != nbytes) { fprintf(stderr, "Error sending answer: %s\n", ssh_get_error(session)); ssh_channel_send_eof(channel); ssh_channel_free(channel); return SSH_ERROR; } printf("Sent answer\n"); } ssh_channel_send_eof(channel); ssh_channel_free(channel); return SSH_OK; }