1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

New command-line option in Plink (and PuTTY, though it's less useful

there): `plink host -nc host2:port' causes the SSH connection's main
channel to be replaced with a direct-tcpip connection to the
specified destination. This feature is mainly designed for use as a
local proxy: setting your local proxy command to `plink %proxyhost
-nc %host:%port' lets you tunnel SSH over SSH with a minimum of
fuss. Works on all platforms.

[originally from svn r6823]
This commit is contained in:
Simon Tatham 2006-08-28 15:12:37 +00:00
parent 8c26b44ce6
commit 631b494807
7 changed files with 133 additions and 10 deletions

View File

@ -249,6 +249,28 @@ int cmdline_process_param(char *p, char *value, int need_save, Config *cfg)
cfg->portfwd[sizeof(cfg->portfwd) - 2] = '\0';
ptr[strlen(ptr)+1] = '\000'; /* append 2nd '\000' */
}
if ((!strcmp(p, "-nc"))) {
char *host, *portp;
RETURN(2);
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
SAVEABLE(0);
host = portp = value;
while (*portp && *portp != ':')
portp++;
if (*portp) {
unsigned len = portp - host;
if (len >= sizeof(cfg->ssh_nc_host))
len = sizeof(cfg->ssh_nc_host) - 1;
strncpy(cfg->ssh_nc_host, value, len);
cfg->ssh_nc_host[sizeof(cfg->ssh_nc_host) - 1] = '\0';
cfg->ssh_nc_port = atoi(portp+1);
} else {
cmdline_error("-nc expects argument of form 'host:port'");
return ret;
}
}
if (!strcmp(p, "-m")) {
char *filename, *command;
int cmdlen, cmdsize;

View File

@ -1807,6 +1807,11 @@ output streams.
This could be used, for instance, to talk to some kind of network proxy
that PuTTY does not natively support; or you could tunnel a connection
over something other than TCP/IP entirely.
If you want your local proxy command to make a secondary SSH
connection to a proxy host and then tunnel the primary connection
over that, you might well want the \c{-nc} command-line option in
Plink. See \k{using-cmdline-ncmode} for more information.
}
\S{config-proxy-exclude} Excluding parts of the network from proxying

View File

@ -796,6 +796,47 @@ at all} checkbox in the SSH panel of the PuTTY configuration box
This option is not available in the file transfer tools PSCP and
PSFTP.
\S2{using-cmdline-ncmode} \I{-nc}\c{-nc}: make a \i{remote network
connection} in place of a remote shell or command
The \c{-nc} option prevents Plink (or PuTTY) from attempting to
start a shell or command on the remote server. Instead, it will
instruct the remote server to open a network connection to a host
name and port number specified by you, and treat that network
connection as if it were the main session.
You specify a host and port as an argument to the \c{-nc} option,
with a colon separating the host name from the port number, like
this:
\c plink host1.example.com -nc host2.example.com:1234
You might want to use this feature if you needed to make an SSH
connection to a target host which you can only reach by going
through a proxy host, and rather than using port forwarding you
prefer to use the local proxy feature (see \k{config-proxy-type} for
more about local proxies). In this situation you might select
\q{Local} proxy type, set your local proxy command to be \cq{plink
%proxyhost -nc %host:%port}, enter the target host name on the
Session panel, and enter the directly reachable proxy host name on
the Proxy panel.
This feature is only available in SSH protocol version 2 (since the
version 1 protocol assumes you will always want to run a shell). It
is not available in the file transfer tools PSCP and PSFTP. It is
available in PuTTY itself, although it is unlikely to be very useful
in any tool other than Plink. Also, \c{-nc} uses the same server
functionality as port forwarding, so it will not work if your server
administrator has disabled port forwarding.
(The option is named \c{-nc} after the Unix program
\W{http://www.vulnwatch.org/netcat/}\c{nc}, short for \q{netcat}.
The command \cq{plink host1 -nc host2:port} is very similar in
functionality to \cq{plink host1 nc host2 port}, which invokes
\c{nc} on the server and tells it to connect to the specified
destination. However, Plink's built-in \c{-nc} option does not
depend on the \c{nc} program being installed on the server.)
\S2{using-cmdline-compress} \I{-C-upper}\c{-C}: enable \i{compression}
The \c{-C} option enables compression of the data sent across the

View File

@ -458,6 +458,8 @@ struct config_tag {
int ssh_subsys; /* run a subsystem rather than a command */
int ssh_subsys2; /* fallback to go with remote_cmd2 */
int ssh_no_shell; /* avoid running a shell */
char ssh_nc_host[512]; /* host to connect to in `nc' mode */
int ssh_nc_port; /* port to connect to in `nc' mode */
/* Telnet options */
char termtype[32];
char termspeed[32];

69
ssh.c
View File

@ -729,6 +729,7 @@ struct ssh_tag {
tree234 *channels; /* indexed by local id */
struct ssh_channel *mainchan; /* primary session channel */
int ncmode; /* is primary channel direct-tcpip? */
int exitcode;
int close_expected;
int clean_exit;
@ -7622,7 +7623,59 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
/*
* Create the main session channel.
*/
if (!ssh->cfg.ssh_no_shell) {
if (ssh->cfg.ssh_no_shell) {
ssh->mainchan = NULL;
} else if (*ssh->cfg.ssh_nc_host) {
/*
* Just start a direct-tcpip channel and use it as the main
* channel.
*/
ssh->mainchan = snew(struct ssh_channel);
ssh->mainchan->ssh = ssh;
ssh->mainchan->localid = alloc_channel_id(ssh);
s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
ssh2_pkt_addstring(s->pktout, "direct-tcpip");
ssh2_pkt_adduint32(s->pktout, ssh->mainchan->localid);
ssh->mainchan->v.v2.locwindow = OUR_V2_WINSIZE;
ssh2_pkt_adduint32(s->pktout, ssh->mainchan->v.v2.locwindow);/* our window size */
ssh2_pkt_adduint32(s->pktout, OUR_V2_MAXPKT); /* our max pkt size */
ssh2_pkt_addstring(s->pktout, ssh->cfg.ssh_nc_host);
ssh2_pkt_adduint32(s->pktout, ssh->cfg.ssh_nc_port);
/*
* We make up values for the originator data; partly it's
* too much hassle to keep track, and partly I'm not
* convinced the server should be told details like that
* about my local network configuration.
* The "originator IP address" is syntactically a numeric
* IP address, and some servers (e.g., Tectia) get upset
* if it doesn't match this syntax.
*/
ssh2_pkt_addstring(s->pktout, "0.0.0.0");
ssh2_pkt_adduint32(s->pktout, 0);
ssh2_pkt_send(ssh, s->pktout);
crWaitUntilV(pktin);
if (pktin->type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) {
bombout(("Server refused to open a direct-tcpip channel"));
crStopV;
/* FIXME: error data comes back in FAILURE packet */
}
if (ssh_pkt_getuint32(pktin) != ssh->mainchan->localid) {
bombout(("Server's channel confirmation cited wrong channel"));
crStopV;
}
ssh->mainchan->remoteid = ssh_pkt_getuint32(pktin);
ssh->mainchan->halfopen = FALSE;
ssh->mainchan->type = CHAN_MAINSESSION;
ssh->mainchan->closes = 0;
ssh->mainchan->v.v2.remwindow = ssh_pkt_getuint32(pktin);
ssh->mainchan->v.v2.remmaxpkt = ssh_pkt_getuint32(pktin);
bufchain_init(&ssh->mainchan->v.v2.outbuffer);
add234(ssh->channels, ssh->mainchan);
update_specials_menu(ssh->frontend);
logevent("Opened direct-tcpip channel in place of session");
ssh->ncmode = TRUE;
} else {
ssh->mainchan = snew(struct ssh_channel);
ssh->mainchan->ssh = ssh;
ssh->mainchan->localid = alloc_channel_id(ssh);
@ -7653,8 +7706,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
add234(ssh->channels, ssh->mainchan);
update_specials_menu(ssh->frontend);
logevent("Opened channel for session");
} else
ssh->mainchan = NULL;
ssh->ncmode = FALSE;
}
/*
* Now we have a channel, make dispatch table entries for
@ -7677,7 +7730,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
/*
* Potentially enable X11 forwarding.
*/
if (ssh->mainchan && ssh->cfg.x11_forward) {
if (ssh->mainchan && !ssh->ncmode && ssh->cfg.x11_forward) {
char proto[20], data[64];
logevent("Requesting X11 forwarding");
ssh->x11auth = x11_invent_auth(proto, sizeof(proto),
@ -7725,7 +7778,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
/*
* Potentially enable agent forwarding.
*/
if (ssh->mainchan && ssh->cfg.agentfwd && agent_exists()) {
if (ssh->mainchan && !ssh->ncmode && ssh->cfg.agentfwd && agent_exists()) {
logevent("Requesting OpenSSH-style agent forwarding");
s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
ssh2_pkt_adduint32(s->pktout, ssh->mainchan->remoteid);
@ -7751,7 +7804,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
/*
* Now allocate a pty for the session.
*/
if (ssh->mainchan && !ssh->cfg.nopty) {
if (ssh->mainchan && !ssh->ncmode && !ssh->cfg.nopty) {
/* Unpick the terminal-speed string. */
/* XXX perhaps we should allow no speeds to be sent. */
ssh->ospeed = 38400; ssh->ispeed = 38400; /* last-resort defaults */
@ -7801,7 +7854,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
* Simplest thing here is to send all the requests at once, and
* then wait for a whole bunch of successes or failures.
*/
if (ssh->mainchan && *ssh->cfg.environmt) {
if (ssh->mainchan && !ssh->ncmode && *ssh->cfg.environmt) {
char *e = ssh->cfg.environmt;
char *var, *varend, *val;
@ -7866,7 +7919,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
* this twice if the config data has provided a second choice
* of command.
*/
if (ssh->mainchan) while (1) {
if (ssh->mainchan && !ssh->ncmode) while (1) {
int subsys;
char *cmd;

View File

@ -813,7 +813,7 @@ int main(int argc, char **argv)
cfg.host[p1] = '\0';
}
if (!cfg.remote_cmd_ptr && !*cfg.remote_cmd)
if (!cfg.remote_cmd_ptr && !*cfg.remote_cmd && !*cfg.ssh_nc_host)
flags |= FLAG_INTERACTIVE;
/*

View File

@ -502,7 +502,7 @@ int main(int argc, char **argv)
cfg.host[p1] = '\0';
}
if (!cfg.remote_cmd_ptr && !*cfg.remote_cmd)
if (!cfg.remote_cmd_ptr && !*cfg.remote_cmd && !*cfg.ssh_nc_host)
flags |= FLAG_INTERACTIVE;
/*