Hello,
first of all -- thanks for Dropbear.
It made me get rid of all remaining rlogin(1) use cases, because
it's so small and inexpensive!
One problem i had with plain, user mode network stack qemu(1)
hostfwd= VMs, however, which yet ended up as, e.g.,
$ dbclient -J 'nc HOST PORT' steffen@crux3
The patch dbear-Y.diff implements a simple replacements of the
arguments of connect_remote(), so that the above ends up without
intermediate nc(1) proxy:
$ dbclient -Y [HOST:]PORT steffen@crux3
Well, i really don't want to miss it again..
dbear-a2i-trail.diff checks that there is no trailing garbage in
the argument to m_str_to_uint(), which silently hit me when
i (stupid) tested -Y with hexadecimal port numbers.
Greetings to Beautiful Australia and ciao,
--steffen
Add '-Y proxyhost:proxyport' option to ease local VM user nets
---
cli-main.c | 14 ++++++++++++--
cli-runopts.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
dbclient.1 | 6 ++++++
runopts.h | 3 ++-
4 files changed, 73 insertions(+), 3 deletions(-)
diff --git a/cli-main.c b/cli-main.c
index 3db8f2f..84979d9 100644
--- a/cli-main.c
+++ b/cli-main.c
@@ -72,8 +72,18 @@ int main(int argc, char ** argv) {
} else
#endif
{
- int sock = connect_remote(cli_opts.remotehost, cli_opts.remoteport,
- 0, &error);
+ int sock;
+ char *h, *p;
+
+ if (cli_opts.proxy_host) {
+ h = cli_opts.proxy_host;
+ p = cli_opts.proxy_port;
+ } else {
+ h = cli_opts.remotehost;
+ p = cli_opts.remoteport;
+ }
+
+ sock = connect_remote(h, p, 0, &error);
sock_in = sock_out = sock;
if (cli_opts.wantpty) {
set_sock_priority(sock, DROPBEAR_PRIO_LOWDELAY);
diff --git a/cli-runopts.c b/cli-runopts.c
index 9877740..53a16d9 100644
--- a/cli-runopts.c
+++ b/cli-runopts.c
@@ -43,6 +43,7 @@ static void loadidentityfile(const char* filename);
#ifdef ENABLE_CLI_ANYTCPFWD
static void addforward(const char* str, m_list *fwdlist);
#endif
+static void add_proxy(const char *str);
#ifdef ENABLE_CLI_NETCAT
static void add_netcat(const char *str);
#endif
@@ -83,6 +84,7 @@ static void printhelp() {
#ifdef ENABLE_CLI_NETCAT
"-B <endhost:endport> Netcat-alike forwarding\n"
#endif
+ "-Y <proxyhost:proxyport> Use proxy socket rather than direct TCP connection\n"
#ifdef ENABLE_CLI_PROXYCMD
"-J <proxy_program> Use program pipe rather than TCP connection\n"
#endif
@@ -114,6 +116,7 @@ void cli_getopts(int argc, char ** argv) {
#ifdef ENABLE_CLI_NETCAT
int nextisnetcat = 0;
#endif
+ int nextisproxy = 0;
char* dummy = NULL; /* Not used for anything real */
char* recv_window_arg = NULL;
@@ -148,6 +151,8 @@ void cli_getopts(int argc, char ** argv) {
cli_opts.agent_fd = -1;
cli_opts.agent_keys_loaded = 0;
#endif
+ cli_opts.proxy_host = NULL;
+ cli_opts.proxy_port = NULL;
#ifdef ENABLE_CLI_PROXYCMD
cli_opts.proxycmd = NULL;
#endif
@@ -200,6 +205,12 @@ void cli_getopts(int argc, char ** argv) {
continue;
}
#endif
+ if (nextisproxy) {
+ TRACE(("nextisproxy true"))
+ add_proxy(argv[i]);
+ nextisproxy = 0;
+ continue;
+ }
if (next) {
/* The previous flag set a value to assign */
*next = argv[i];
@@ -267,6 +278,9 @@ void cli_getopts(int argc, char ** argv) {
nextisnetcat = 1;
break;
#endif
+ case 'Y':
+ nextisproxy = 1;
+ break;
#ifdef ENABLE_CLI_PROXYCMD
case 'J':
next = &cli_opts.proxycmd;
@@ -632,6 +646,45 @@ static void parse_hostname(const char* orighostarg) {
}
}
+static void add_proxy(const char* origstr) {
+ unsigned int port;
+ char *portstr, *str;
+
+ str = m_strdup(origstr);
+
+ portstr = strchr(str, ':');
+ if (portstr == NULL) {
+ portstr = str;
+ str = m_strdup("localhost");
+ } else {
+ *portstr = '\0';
+ ++portstr;
+ portstr = m_strdup(portstr);
+
+ if (strchr(portstr, ':')) {
+ TRACE(("Multiple proxy colons"))
+ goto fail;
+ }
+ }
+
+ if (m_str_to_uint(portstr, &port) == DROPBEAR_FAILURE) {
+ TRACE(("bad proxy port"))
+ goto fail;
+ }
+
+ if (port > 65535) {
+ TRACE(("too large proxy port"))
+ goto fail;
+ }
+
+ cli_opts.proxy_host = str;
+ cli_opts.proxy_port = portstr;
+ return;
+
+fail:
+ dropbear_exit("Bad proxy endpoint '%s'", origstr);
+}
+
#ifdef ENABLE_CLI_NETCAT
static void add_netcat(const char* origstr) {
char *portstr = NULL;
diff --git a/dbclient.1 b/dbclient.1
index 4839982..a3d5fbc 100644
--- a/dbclient.1
+++ b/dbclient.1
@@ -108,6 +108,12 @@ Use the standard input/output of the program \fIproxy_command\fR rather than usi
a normal TCP connection. A hostname should be still be provided, as this is used for
comparing saved hostkeys.
.TP
+.B \-Y \fI[proxyhost:]proxyport
+Create a network connection to \fI[proxyhost:]proxyport\fR and use that as
+standard input/output. If \fIproxyhost\fR is omitted, \fIlocalhost\fR is
+used. A hostname should be still be provided, as this is used for
+comparing saved hostkeys.
+.TP
.B \-B \fIendhost:endport
"Netcat-alike" mode, where Dropbear will connect to the given host, then create a
forwarded connection to \fIendhost\fR. This will then be presented as dbclient's
diff --git a/runopts.h b/runopts.h
index 21fc8e5..c72f009 100644
--- a/runopts.h
+++ b/runopts.h
@@ -147,11 +147,12 @@ typedef struct cli_runopts {
int agent_fd; /* The agent fd is only set during authentication. Forwarded
agent sessions have their own file descriptors */
#endif
-
#ifdef ENABLE_CLI_NETCAT
char *netcat_host;
unsigned int netcat_port;
#endif
+ char *proxy_host;
+ char *proxy_port;
#ifdef ENABLE_CLI_PROXYCMD
char *proxycmd;
#endif
m_str_to_uint(): ensure there is no trailing garbage in input
---
dbutil.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/dbutil.c b/dbutil.c
index 082a5a2..2b59122 100644
--- a/dbutil.c
+++ b/dbutil.c
@@ -901,14 +901,16 @@ void disallow_core() {
/* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE, with the result in *val */
int m_str_to_uint(const char* str, unsigned int *val) {
+ char *ep;
unsigned long l;
errno = 0;
- l = strtoul(str, NULL, 10);
+ l = strtoul(str, &ep, 10);
/* The c99 spec doesn't actually seem to define EINVAL, but most platforms
* I've looked at mention it in their manpage */
if ((l == 0 && errno == EINVAL)
|| (l == ULONG_MAX && errno == ERANGE)
- || (l > UINT_MAX)) {
+ || (l > UINT_MAX)
+ || *str == '\0' || *ep != '\0') {
return DROPBEAR_FAILURE;
} else {
*val = l;