зеркало из https://github.com/Azure/sonic-openssh.git
- markus@cvs.openbsd.org 2001/04/07 08:55:18
[buffer.c channels.c channels.h readconf.c ssh.c] allow the ssh client act as a SOCKS4 proxy (dynamic local portforwarding). work by Dan Kaminsky <dankamin@cisco.com> and me. thanks to Dan for this great patch: use 'ssh -D 1080 host' and make netscape use localhost:1080 as a socks proxy.
This commit is contained in:
Родитель
3fcf1a22b5
Коммит
3bb4f9da73
|
@ -15,6 +15,12 @@
|
|||
do gid/groups-swap in addition to uid-swap, should help if /home/group
|
||||
is chmod 750 + chgrp grp /home/group/, work be deraadt and me, thanks
|
||||
to olar@openwall.com is comments. we had many requests for this.
|
||||
- markus@cvs.openbsd.org 2001/04/07 08:55:18
|
||||
[buffer.c channels.c channels.h readconf.c ssh.c]
|
||||
allow the ssh client act as a SOCKS4 proxy (dynamic local
|
||||
portforwarding). work by Dan Kaminsky <dankamin@cisco.com> and me.
|
||||
thanks to Dan for this great patch: use 'ssh -D 1080 host' and make
|
||||
netscape use localhost:1080 as a socks proxy.
|
||||
|
||||
20010408
|
||||
- OpenBSD CVS Sync
|
||||
|
@ -4955,4 +4961,4 @@
|
|||
- Wrote replacements for strlcpy and mkdtemp
|
||||
- Released 1.0pre1
|
||||
|
||||
$Id: ChangeLog,v 1.1083 2001/04/08 18:26:59 mouring Exp $
|
||||
$Id: ChangeLog,v 1.1084 2001/04/08 18:30:26 mouring Exp $
|
||||
|
|
4
buffer.c
4
buffer.c
|
@ -12,7 +12,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: buffer.c,v 1.11 2001/04/05 21:02:46 markus Exp $");
|
||||
RCSID("$OpenBSD: buffer.c,v 1.12 2001/04/07 08:55:15 markus Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "buffer.h"
|
||||
|
@ -156,5 +156,5 @@ buffer_dump(Buffer *buffer)
|
|||
|
||||
for (i = buffer->offset; i < buffer->end; i++)
|
||||
fprintf(stderr, " %02x", ucp[i]);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "\r\n");
|
||||
}
|
||||
|
|
220
channels.c
220
channels.c
|
@ -40,7 +40,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: channels.c,v 1.102 2001/04/06 21:00:10 markus Exp $");
|
||||
RCSID("$OpenBSD: channels.c,v 1.103 2001/04/07 08:55:17 markus Exp $");
|
||||
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/dsa.h>
|
||||
|
@ -51,6 +51,7 @@ RCSID("$OpenBSD: channels.c,v 1.102 2001/04/06 21:00:10 markus Exp $");
|
|||
#include "packet.h"
|
||||
#include "xmalloc.h"
|
||||
#include "buffer.h"
|
||||
#include "bufaux.h"
|
||||
#include "uidswap.h"
|
||||
#include "log.h"
|
||||
#include "misc.h"
|
||||
|
@ -133,6 +134,8 @@ static int have_hostname_in_open = 0;
|
|||
/* AF_UNSPEC or AF_INET or AF_INET6 */
|
||||
extern int IPv4or6;
|
||||
|
||||
void port_open_helper(Channel *c, char *rtype);
|
||||
|
||||
/* Sets specific protocol options. */
|
||||
|
||||
void
|
||||
|
@ -539,6 +542,89 @@ channel_pre_x11_open(Channel *c, fd_set * readset, fd_set * writeset)
|
|||
}
|
||||
}
|
||||
|
||||
#define SSH_SOCKS_HEAD 1+1+2+4
|
||||
|
||||
void
|
||||
channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset)
|
||||
{
|
||||
u_char *p, *host;
|
||||
int len, i, done, have;
|
||||
char username[256];
|
||||
struct {
|
||||
u_int8_t version;
|
||||
u_int8_t command;
|
||||
u_int16_t dest_port;
|
||||
struct in_addr dest_ip;
|
||||
} s4_req, s4_rsp;
|
||||
|
||||
have = buffer_len(&c->input);
|
||||
|
||||
debug("channel %d: pre_dynamic have: %d", c->self, have);
|
||||
/*buffer_dump(&c->input);*/
|
||||
|
||||
/* Check if the fixed size part of the packet is in buffer. */
|
||||
if (have < SSH_SOCKS_HEAD + 1) {
|
||||
/* need more */
|
||||
FD_SET(c->sock, readset);
|
||||
return;
|
||||
}
|
||||
/* Check for end of username */
|
||||
p = buffer_ptr(&c->input);
|
||||
done = 0;
|
||||
for (i = SSH_SOCKS_HEAD; i < have; i++) {
|
||||
if (p[i] == '\0') {
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!done) {
|
||||
/* need more */
|
||||
FD_SET(c->sock, readset);
|
||||
return;
|
||||
}
|
||||
buffer_get(&c->input, (char *)&s4_req.version, 1);
|
||||
buffer_get(&c->input, (char *)&s4_req.command, 1);
|
||||
buffer_get(&c->input, (char *)&s4_req.dest_port, 2);
|
||||
buffer_get(&c->input, (char *)&s4_req.dest_ip, 4);
|
||||
p = buffer_ptr(&c->input);
|
||||
len = strlen(p);
|
||||
have = buffer_len(&c->input);
|
||||
debug2("channel %d: pre_dynamic user: %s/%d", c->self, p, len);
|
||||
if (len > have)
|
||||
fatal("channel %d: pre_dynamic: len %d > have %d",
|
||||
c->self, len, have);
|
||||
strlcpy(username, p, sizeof(username));
|
||||
buffer_consume(&c->input, len);
|
||||
buffer_consume(&c->input, 1); /* trailing '\0' */
|
||||
|
||||
host = inet_ntoa(s4_req.dest_ip);
|
||||
strlcpy(c->path, host, sizeof(c->path));
|
||||
c->host_port = ntohs(s4_req.dest_port);
|
||||
|
||||
debug("channel %d: dynamic request received: "
|
||||
"socks%x://%s@%s:%u/command?%u",
|
||||
c->self, s4_req.version, username, host, c->host_port,
|
||||
s4_req.command);
|
||||
|
||||
if ((s4_req.version != 4) || (s4_req.command != 1)) {
|
||||
debug("channel %d: cannot handle: socks VN %d CN %d",
|
||||
c->self, s4_req.version, s4_req.command);
|
||||
channel_free(c->self);
|
||||
return;
|
||||
}
|
||||
|
||||
s4_rsp.version = 0; /* VN: version of reply code */
|
||||
s4_rsp.command = 90; /* CD: request granted */
|
||||
s4_rsp.dest_port = 0; /* ignored */
|
||||
s4_rsp.dest_ip.s_addr = INADDR_ANY; /* ignored */
|
||||
buffer_append(&c->output, (char *)&s4_rsp, sizeof(s4_rsp));
|
||||
|
||||
/* switch to next state */
|
||||
c->type = SSH_CHANNEL_OPENING;
|
||||
port_open_helper(c, "direct-tcpip");
|
||||
}
|
||||
|
||||
|
||||
/* This is our fake X11 server socket. */
|
||||
void
|
||||
channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset)
|
||||
|
@ -591,57 +677,39 @@ channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This socket is listening for connections to a forwarded TCP/IP port.
|
||||
*/
|
||||
void
|
||||
channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
|
||||
port_open_helper(Channel *c, char *rtype)
|
||||
{
|
||||
struct sockaddr addr;
|
||||
int newsock, newch;
|
||||
socklen_t addrlen;
|
||||
char buf[1024], *remote_ipaddr, *rtype;
|
||||
int remote_port;
|
||||
int direct;
|
||||
char buf[1024];
|
||||
char *remote_ipaddr = get_peer_ipaddr(c->sock);
|
||||
u_short remote_port = get_peer_port(c->sock);
|
||||
|
||||
rtype = (c->type == SSH_CHANNEL_RPORT_LISTENER) ?
|
||||
"forwarded-tcpip" : "direct-tcpip";
|
||||
direct = (strcmp(rtype, "direct-tcpip") == 0);
|
||||
|
||||
if (FD_ISSET(c->sock, readset)) {
|
||||
debug("Connection to port %d forwarding "
|
||||
"to %.100s port %d requested.",
|
||||
c->listening_port, c->path, c->host_port);
|
||||
addrlen = sizeof(addr);
|
||||
newsock = accept(c->sock, &addr, &addrlen);
|
||||
if (newsock < 0) {
|
||||
error("accept: %.100s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
remote_ipaddr = get_peer_ipaddr(newsock);
|
||||
remote_port = get_peer_port(newsock);
|
||||
snprintf(buf, sizeof buf,
|
||||
"listen port %d for %.100s port %d, "
|
||||
"%s: listening port %d for %.100s port %d, "
|
||||
"connect from %.200s port %d",
|
||||
c->listening_port, c->path, c->host_port,
|
||||
rtype, c->listening_port, c->path, c->host_port,
|
||||
remote_ipaddr, remote_port);
|
||||
|
||||
newch = channel_new(rtype,
|
||||
SSH_CHANNEL_OPENING, newsock, newsock, -1,
|
||||
c->local_window_max, c->local_maxpacket,
|
||||
0, xstrdup(buf), 1);
|
||||
xfree(c->remote_name);
|
||||
c->remote_name = xstrdup(buf);
|
||||
|
||||
if (compat20) {
|
||||
packet_start(SSH2_MSG_CHANNEL_OPEN);
|
||||
packet_put_cstring(rtype);
|
||||
packet_put_int(newch);
|
||||
packet_put_int(c->self);
|
||||
packet_put_int(c->local_window_max);
|
||||
packet_put_int(c->local_maxpacket);
|
||||
if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
|
||||
/* listen address, port */
|
||||
packet_put_string(c->path, strlen(c->path));
|
||||
packet_put_int(c->listening_port);
|
||||
} else {
|
||||
if (direct) {
|
||||
/* target host, port */
|
||||
packet_put_string(c->path, strlen(c->path));
|
||||
packet_put_cstring(c->path);
|
||||
packet_put_int(c->host_port);
|
||||
} else {
|
||||
/* listen address, port */
|
||||
packet_put_cstring(c->path);
|
||||
packet_put_int(c->listening_port);
|
||||
}
|
||||
/* originator host and port */
|
||||
packet_put_cstring(remote_ipaddr);
|
||||
|
@ -649,16 +717,61 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
|
|||
packet_send();
|
||||
} else {
|
||||
packet_start(SSH_MSG_PORT_OPEN);
|
||||
packet_put_int(newch);
|
||||
packet_put_string(c->path, strlen(c->path));
|
||||
packet_put_int(c->self);
|
||||
packet_put_cstring(c->path);
|
||||
packet_put_int(c->host_port);
|
||||
if (have_hostname_in_open) {
|
||||
packet_put_string(buf, strlen(buf));
|
||||
}
|
||||
if (have_hostname_in_open)
|
||||
packet_put_cstring(c->remote_name);
|
||||
packet_send();
|
||||
}
|
||||
xfree(remote_ipaddr);
|
||||
}
|
||||
|
||||
/*
|
||||
* This socket is listening for connections to a forwarded TCP/IP port.
|
||||
*/
|
||||
void
|
||||
channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
|
||||
{
|
||||
Channel *nc;
|
||||
struct sockaddr addr;
|
||||
int newsock, newch, nextstate;
|
||||
socklen_t addrlen;
|
||||
char *rtype;
|
||||
|
||||
if (FD_ISSET(c->sock, readset)) {
|
||||
debug("Connection to port %d forwarding "
|
||||
"to %.100s port %d requested.",
|
||||
c->listening_port, c->path, c->host_port);
|
||||
|
||||
rtype = (c->type == SSH_CHANNEL_RPORT_LISTENER) ?
|
||||
"forwarded-tcpip" : "direct-tcpip";
|
||||
nextstate = (c->host_port == 0) ? SSH_CHANNEL_DYNAMIC :
|
||||
SSH_CHANNEL_OPENING;
|
||||
|
||||
addrlen = sizeof(addr);
|
||||
newsock = accept(c->sock, &addr, &addrlen);
|
||||
if (newsock < 0) {
|
||||
error("accept: %.100s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
newch = channel_new(rtype,
|
||||
nextstate, newsock, newsock, -1,
|
||||
c->local_window_max, c->local_maxpacket,
|
||||
0, xstrdup(rtype), 1);
|
||||
|
||||
nc = channel_lookup(newch);
|
||||
if (nc == NULL) {
|
||||
error("xxx: no new channel:");
|
||||
return;
|
||||
}
|
||||
nc->listening_port = c->listening_port;
|
||||
nc->host_port = c->host_port;
|
||||
strlcpy(nc->path, c->path, sizeof(nc->path));
|
||||
|
||||
if (nextstate != SSH_CHANNEL_DYNAMIC)
|
||||
port_open_helper(nc, rtype);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -733,6 +846,15 @@ channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset)
|
|||
if (len <= 0) {
|
||||
debug("channel %d: read<=0 rfd %d len %d",
|
||||
c->self, c->rfd, len);
|
||||
if (c->type == SSH_CHANNEL_DYNAMIC) {
|
||||
/*
|
||||
* we are not yet connected to a remote peer,
|
||||
* so the connection-close protocol won't work
|
||||
*/
|
||||
debug("channel %d: dynamic: closed", c->self);
|
||||
channel_free(c->self);
|
||||
return -1;
|
||||
}
|
||||
if (compat13) {
|
||||
buffer_consume(&c->output, buffer_len(&c->output));
|
||||
c->type = SSH_CHANNEL_INPUT_DRAINING;
|
||||
|
@ -893,6 +1015,12 @@ channel_post_output_drain_13(Channel *c, fd_set * readset, fd_set * writeset)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
channel_post_dynamic(Channel *c, fd_set * readset, fd_set * writeset)
|
||||
{
|
||||
channel_handle_rfd(c, readset, writeset);
|
||||
}
|
||||
|
||||
void
|
||||
channel_handler_init_20(void)
|
||||
{
|
||||
|
@ -903,6 +1031,7 @@ channel_handler_init_20(void)
|
|||
channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
|
||||
channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
|
||||
channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
|
||||
channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
|
||||
|
||||
channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_2;
|
||||
channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
|
||||
|
@ -910,6 +1039,7 @@ channel_handler_init_20(void)
|
|||
channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
|
||||
channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
|
||||
channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
|
||||
channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_dynamic;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -923,6 +1053,7 @@ channel_handler_init_13(void)
|
|||
channel_pre[SSH_CHANNEL_INPUT_DRAINING] = &channel_pre_input_draining;
|
||||
channel_pre[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_pre_output_draining;
|
||||
channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
|
||||
channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
|
||||
|
||||
channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_1;
|
||||
channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
|
||||
|
@ -930,6 +1061,7 @@ channel_handler_init_13(void)
|
|||
channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
|
||||
channel_post[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_post_output_drain_13;
|
||||
channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
|
||||
channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_dynamic;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -941,12 +1073,14 @@ channel_handler_init_15(void)
|
|||
channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
|
||||
channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
|
||||
channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
|
||||
channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
|
||||
|
||||
channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
|
||||
channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
|
||||
channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
|
||||
channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_1;
|
||||
channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
|
||||
channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_dynamic;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1500,6 +1634,7 @@ channel_still_open()
|
|||
case SSH_CHANNEL_RPORT_LISTENER:
|
||||
case SSH_CHANNEL_CLOSED:
|
||||
case SSH_CHANNEL_AUTH_SOCKET:
|
||||
case SSH_CHANNEL_DYNAMIC:
|
||||
case SSH_CHANNEL_CONNECTING: /* XXX ??? */
|
||||
continue;
|
||||
case SSH_CHANNEL_LARVAL:
|
||||
|
@ -1551,6 +1686,7 @@ channel_open_message()
|
|||
case SSH_CHANNEL_LARVAL:
|
||||
case SSH_CHANNEL_OPENING:
|
||||
case SSH_CHANNEL_CONNECTING:
|
||||
case SSH_CHANNEL_DYNAMIC:
|
||||
case SSH_CHANNEL_OPEN:
|
||||
case SSH_CHANNEL_X11_OPEN:
|
||||
case SSH_CHANNEL_INPUT_DRAINING:
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/* RCSID("$OpenBSD: channels.h,v 1.29 2001/04/04 20:25:36 markus Exp $"); */
|
||||
/* RCSID("$OpenBSD: channels.h,v 1.30 2001/04/07 08:55:17 markus Exp $"); */
|
||||
|
||||
#ifndef CHANNELS_H
|
||||
#define CHANNELS_H
|
||||
|
@ -53,7 +53,8 @@
|
|||
#define SSH_CHANNEL_LARVAL 10 /* larval session */
|
||||
#define SSH_CHANNEL_RPORT_LISTENER 11 /* Listening to a R-style port */
|
||||
#define SSH_CHANNEL_CONNECTING 12
|
||||
#define SSH_CHANNEL_MAX_TYPE 13
|
||||
#define SSH_CHANNEL_DYNAMIC 13
|
||||
#define SSH_CHANNEL_MAX_TYPE 14
|
||||
|
||||
/*
|
||||
* Data structure for channel data. This is iniailized in channel_allocate
|
||||
|
|
17
readconf.c
17
readconf.c
|
@ -12,7 +12,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: readconf.c,v 1.70 2001/04/02 14:20:23 stevesk Exp $");
|
||||
RCSID("$OpenBSD: readconf.c,v 1.71 2001/04/07 08:55:17 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "xmalloc.h"
|
||||
|
@ -110,7 +110,7 @@ typedef enum {
|
|||
oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
|
||||
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
|
||||
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
|
||||
oPreferredAuthentications
|
||||
oDynamicForward, oPreferredAuthentications
|
||||
} OpCodes;
|
||||
|
||||
/* Textual representations of the tokens. */
|
||||
|
@ -172,6 +172,7 @@ static struct {
|
|||
{ "keepalive", oKeepAlives },
|
||||
{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
|
||||
{ "loglevel", oLogLevel },
|
||||
{ "dynamicforward", oDynamicForward },
|
||||
{ "preferredauthentications", oPreferredAuthentications },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
@ -583,6 +584,18 @@ parse_int:
|
|||
add_local_forward(options, fwd_port, buf, fwd_host_port);
|
||||
break;
|
||||
|
||||
case oDynamicForward:
|
||||
arg = strdelim(&s);
|
||||
if (!arg || *arg == '\0')
|
||||
fatal("%.200s line %d: Missing port argument.",
|
||||
filename, linenum);
|
||||
if (arg[0] < '0' || arg[0] > '9')
|
||||
fatal("%.200s line %d: Badly formatted port number.",
|
||||
filename, linenum);
|
||||
fwd_port = atoi(arg);
|
||||
add_local_forward(options, fwd_port, "socks4", 0);
|
||||
break;
|
||||
|
||||
case oHost:
|
||||
*activep = 0;
|
||||
while ((arg = strdelim(&s)) != NULL && *arg != '\0')
|
||||
|
|
13
ssh.c
13
ssh.c
|
@ -39,7 +39,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: ssh.c,v 1.107 2001/04/06 21:00:13 markus Exp $");
|
||||
RCSID("$OpenBSD: ssh.c,v 1.108 2001/04/07 08:55:18 markus Exp $");
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
|
@ -178,6 +178,9 @@ usage(void)
|
|||
fprintf(stderr, " -R listen-port:host:port Forward remote port to local address\n");
|
||||
fprintf(stderr, " These cause %s to listen for connections on a port, and\n", __progname);
|
||||
fprintf(stderr, " forward them to the other side by connecting to host:port.\n");
|
||||
fprintf(stderr, " -D port Dynamically forward local port to multiple remote addresses.\n");
|
||||
fprintf(stderr, " Allows SSH to act as an application-layer proxy.\n");
|
||||
fprintf(stderr, " Protocols Supported: SOCKS4\n");
|
||||
fprintf(stderr, " -C Enable compression.\n");
|
||||
fprintf(stderr, " -N Do not execute a shell or command.\n");
|
||||
fprintf(stderr, " -g Allow remote hosts to connect to forwarded ports.\n");
|
||||
|
@ -314,7 +317,7 @@ main(int ac, char **av)
|
|||
opt = av[optind][1];
|
||||
if (!opt)
|
||||
usage();
|
||||
if (strchr("eilcmpLRo", opt)) { /* options with arguments */
|
||||
if (strchr("eilcmpLRDo", opt)) { /* options with arguments */
|
||||
optarg = av[optind] + 2;
|
||||
if (strcmp(optarg, "") == 0) {
|
||||
if (optind >= ac - 1)
|
||||
|
@ -480,6 +483,12 @@ main(int ac, char **av)
|
|||
}
|
||||
add_local_forward(&options, fwd_port, buf, fwd_host_port);
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
fwd_port = atoi(optarg);
|
||||
add_local_forward(&options, fwd_port, "socks4", 0);
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
options.compression = 1;
|
||||
break;
|
||||
|
|
Загрузка…
Ссылка в новой задаче