Re: Remote program doesn't terminate when ssh session ends
Years ago, I attempted to fix an issue that sounds a lot like this: https://hg.ucc.asn.au/dropbear/rev/35183e8a7851 I believe the right way this works it that: - ssh client closes session - dropbear closes the read end of command's stdout pipe - next time command writes to pipe, it receives SIGPIPE and dies Thus I don't think dropbear needs to explicitly kill anything. but perhaps the mechanism is somehow not working. I would investigate this by running 'strace' on the remote host and seeing if, after closing the session, 1) dropbear closes the pipe and 2) the command tries to write to it and receives SIGPIPE. On Thu, Feb 25, 2021 at 12:52 PM Grant Edwards wrote: > I have a small ash script that prints memory statistics once a second: > > #!/bin/sh > > while true > do > date > cat /proc/[0-9]*/stat | > awk '$23 > 0 {printf "%5d %20s %8d %5d\n", $1, $2, $23, $24}' | > sort -n > sleep 60 > done > > When I run that remotely via dropbea: > > $ ssh root@10.0.0.99 ./showmem.sh > > Everything works as expected while the ssh session is active, but when > I end the ssh connection, the shell script never terminates: it > continues to run (indifinitely, AFAICT). I don't recall this happening > when we used to use openssh's server. Is there any way to get dropbear > to terminate a "child" program when the ssh session closes? > > > > >
[PATCH] Handle invalid agent keys by skipping rather than exiting.
dropbear-skip-bad-key.patch Description: Binary data
Re: TOS byte on port forwarding-only connections
On Tue, Jul 8, 2014 at 9:44 AM, Matt Johnston m...@ucc.asn.au wrote: I'm not really sure how to resolve it though. Maybe as a tradeoff the refcounting could just switch between LOWDELAY and no-tos-flags if there are TCP forwards going on, then BULK if there aren't TCP forwards? Ok, so if I'm understanding correctly, the invariant would be something like: if (connecting || ptys) tos = LOWDELAY; else if (tcp_forwards) tos = 0; else tos = BULK; This might be implemented cleverly so that it's only reapplied on 0/1 transitions of ptys and tcp_forwards, but these would be the high-level semantics?
[PATCH] Set IPTOS_LOWDELAY on PTY sessions only
Signed-off-by: Catalin Patulea c...@vv.carleton.ca --- cli-chansession.c | 1 + dbutil.c | 29 + dbutil.h | 2 ++ includes.h| 4 svr-chansession.c | 2 ++ 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/cli-chansession.c b/cli-chansession.c index 0ee3e85..b99e073 100644 --- a/cli-chansession.c +++ b/cli-chansession.c @@ -369,6 +369,7 @@ static int cli_initchansess(struct Channel *channel) { if (cli_opts.wantpty) { send_chansess_pty_req(channel); + set_sock_priority(ses.sock_out); } send_chansess_shell_req(channel); diff --git a/dbutil.c b/dbutil.c index ce88731..4f15027 100644 --- a/dbutil.c +++ b/dbutil.c @@ -177,28 +177,41 @@ void dropbear_trace2(const char* format, ...) { } #endif /* DEBUG_TRACE */ -static void set_sock_priority(int sock) { - +void set_sock_nodelay(int sock) { int val; /* disable nagle */ val = 1; setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)val, sizeof(val)); +} + +void set_sock_priority(int sock) { + + int val, rc; /* set the TOS bit for either ipv4 or ipv6 */ #ifdef IPTOS_LOWDELAY val = IPTOS_LOWDELAY; #if defined(IPPROTO_IPV6) defined(IPV6_TCLASS) - setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, (void*)val, sizeof(val)); + rc = setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, (void*)val, sizeof(val)); + if (rc 0) + dropbear_log(LOG_WARNING, Couldn't set IPV6_TCLASS (%s), + strerror(errno)); #endif - setsockopt(sock, IPPROTO_IP, IP_TOS, (void*)val, sizeof(val)); + rc = setsockopt(sock, IPPROTO_IP, IP_TOS, (void*)val, sizeof(val)); + if (rc 0) + dropbear_log(LOG_WARNING, Couldn't set IP_TOS (%s), + strerror(errno)); #endif #ifdef SO_PRIORITY /* linux specific, sets QoS class. * 6 looks to be optimal for interactive traffic (see tc-prio(8) ). */ - val = 6; - setsockopt(sock, SOL_SOCKET, SO_PRIORITY, (void*) val, sizeof(val)); + val = TC_PRIO_INTERACTIVE; + rc = setsockopt(sock, SOL_SOCKET, SO_PRIORITY, (void*) val, sizeof(val)); + if (rc 0) + dropbear_log(LOG_WARNING, Couldn't set SO_PRIORITY (%s), + strerror(errno)); #endif } @@ -290,7 +303,7 @@ int dropbear_listen(const char* address, const char* port, } #endif - set_sock_priority(sock); + set_sock_nodelay(sock); if (bind(sock, res-ai_addr, res-ai_addrlen) 0) { err = errno; @@ -429,7 +442,7 @@ int connect_remote(const char* remotehost, const char* remoteport, TRACE((Error connecting: %s, strerror(err))) } else { /* Success */ - set_sock_priority(sock); + set_sock_nodelay(sock); } freeaddrinfo(res0); diff --git a/dbutil.h b/dbutil.h index 7c7435c..7665845 100644 --- a/dbutil.h +++ b/dbutil.h @@ -66,6 +66,8 @@ void get_socket_address(int fd, char **local_host, char **local_port, char **remote_host, char **remote_port, int host_lookup); void getaddrstring(struct sockaddr_storage* addr, char **ret_host, char **ret_port, int host_lookup); +void set_sock_nodelay(int sock); +void set_sock_priority(int sock); int dropbear_listen(const char* address, const char* port, int *socks, unsigned int sockcount, char **errstring, int *maxfd); int spawn_command(void(*exec_fn)(void *user_data), void *exec_data, diff --git a/includes.h b/includes.h index 62a8d73..bae82f5 100644 --- a/includes.h +++ b/includes.h @@ -156,6 +156,10 @@ typedef unsigned int u_int32_t; typedef u_int32_t uint32_t; #endif /* HAVE_UINT32_T */ +#ifdef SO_PRIORITY +#include linux/pkt_sched.h +#endif + #include fake-rfc2553.h #ifndef LOG_AUTHPRIV diff --git a/svr-chansession.c b/svr-chansession.c index b585a9a..b912eaf 100644 --- a/svr-chansession.c +++ b/svr-chansession.c @@ -580,6 +580,8 @@ static int sessionpty(struct ChanSess * chansess) { /* Read the terminal modes */ get_termmodes(chansess); + set_sock_priority(ses.sock_out); + TRACE((leave sessionpty)) return DROPBEAR_SUCCESS; } -- 1.8.4.1
[PATCH] Fix TRACEs of cli_send_netcat_request
Signed-off-by: Catalin Patulea c...@vv.carleton.ca --- cli-chansession.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cli-chansession.c b/cli-chansession.c index ed80453..0ee3e85 100644 --- a/cli-chansession.c +++ b/cli-chansession.c @@ -398,6 +398,7 @@ void cli_send_netcat_request() { const unsigned char* source_host = 127.0.0.1; const int source_port = 22; + TRACE((enter cli_send_netcat_request)) cli_opts.wantpty = 0; if (send_msg_channel_open_init(STDIN_FILENO, cli_chan_netcat) @@ -414,7 +415,7 @@ void cli_send_netcat_request() { buf_putint(ses.writepayload, source_port); encrypt_packet(); - TRACE((leave cli_send_chansess_request)) + TRACE((leave cli_send_netcat_request)) } #endif -- 1.8.4.1
Re: TOS byte for bulk transfers
On Sat, Nov 23, 2013 at 4:26 PM, Dave Taht dave.t...@gmail.com wrote: While obsolete (don't use it!) , wondershaper was the root of all these systems a decade ago, and is a lot easier to study and understand than these successors. Thanks for the pointers. Indeed, I use a simplified variant of wondershaper at my gateway. TBF at the root to take control of the queue, PRIO to respect the TOS byte, then FIFO in the low latency band (I want it to starve anything else - which is exactly what happened), fq_codel in the rest. In a sense, my gateway worked exactly as intended - it's just that the application layer was giving it mixed signals. I guess the direction I'm trying to go is patching dropbear in some way to cooperate better with this sort of shaping. In a way, I'm asking, Matt, what kind of patch would you accept here? Another idea that occurred to me offline (I swear, I only later checked what OpenSSH does) would be to key off things like PTY requests. Most likely those sessions are interactive, while others that request a subsystem or no PTY are probably bulk. In fact this is one of the main things OpenSSH does. There's two sides to the story, so let me start client first: http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/clientloop.c?rev=1.256 In client_session2_setup(): - packet_set_interactive(want_tty, ...) http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/ssh.c?rev=1.393 In ssh_session(): - packet_set_interactive(interactive /* = request_pty_succeeded || x11_forwarding */,) In ssh_session2_setup() - packet_set_interactive(interactive /* = similar logic as ssh_session */) and now server: http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/session.c?rev=1.268 In do_exec_no_pty(): - packet_set_interactive(s-display != NULL, ...); // Haven't verified where s-display comes from, but I get it amounts to x11 forwarding is enabled. In do_exec_pty(): - packet_set_interactive(1, ...); packet_set_interactive just ends up doing setsockopt. So there is precedent for doing a bit of cleverness at the application layer to help the network layer. For myself, just keying off pty requests would have been enough to trigger the correct whole-system behaviour. Matt, would you accept a patch that keys the TOS setting off PTY requests?
Re: TOS byte for bulk transfers
On Sat, Nov 23, 2013 at 9:11 PM, Matt Johnston m...@ucc.asn.au wrote: Catalin Patulea c...@vv.carleton.ca wrote: Matt, would you accept a patch that keys the TOS setting off PTY requests? Yes, I've been meaning to look at that. Heads up, client and server TCP port forwards use the same utility function, connect_remote, so changes in this area will also affect those connections. It seems sensible to me that they be downgraded to default TOS (00), what do you think?
Re: autossh incompatibility with dropbear -y
You could always write a small wrapper script that adds whatever command-line arguments you need, and pass *that* to autossh. #!/bin/sh exec path/to/dropbear -y $@ On Fri, Oct 4, 2013 at 12:31 PM, Steve Newcomb s...@coolheads.com wrote: I'm using OpenWRT. My router, whose IP address changes unpredictably, makes its ssh-listening port available on another host running at a stable IP address, using autossh/dropbear to create a reverse channel. Sometimes the host's key changes from time to time, which can stop the autossh process at a prompt (to nobody) to decide what to do about the change. Ordinary OpenSSH has a StrictHostKeyChecking option which can be used to bypass the so-called ask prompt and just make the connection regardless. By reading the source, I learned that Dropbear's ssh client evidently has a similar feature, the -y invocation option. But I can't pass the -y to it via autossh because autossh doesn't approve of it. Dropbear's ssh client also does not offer a config file utility, AFAIK. Dropbear evidently ignores all -o options, too; they wind up in a bit bucket called something like dummy. Does anybody know the answer, short of editing/recompiling autossh so it won't be so persnickety and just get out of the way? Steve Newcomb
Re: implementing e...@openssh.com
Something else to note about e...@openssh.com is that OpenSSH only sends this request to peer implementations which are whitelisted (currently only OpenSSH*). Historicaly, other impls have been buggy to the point of crashing when they receive e...@openssh.com, so they set up this whitelist to reduce interop issues. In fact dropbear is one of the bad impls, because when the client sees a channel request it doesn't recognize, it always does send_msg_channel_failure. It should instead look at 'wantreply' and if it's FALSE, it should drop the request silently. The patch dropbear-eow.patch fixes this. But all this to say that vanilla OpenSSH cannot be used to test this feature because it won't send e...@openssh.com. OpenSSH would need to be patched to include dropbear in the whitelist for testing. On Wed, Jul 24, 2013 at 9:21 PM, Catalin Patulea c...@vv.carleton.ca wrote: e...@openssh.com is an extension that allows EPIPE to propagate through SSH sessions. For example: ssh localhost cat /dev/urandom | /bin/true will very quickly exit because /bin/true does not consume its stdin. The mechanism is: - /bin/true calls exit(0), closing the last remaining ref to its stdin pipe - ssh tries to write() and gets EPIPE - ssh sends e...@openssh.com channel request to server - sshd handles e...@openssh.com by closing read side of its pipe - 'cat /etc/urandom' itself tries to write(), sees EPIPE and is killed by SIGPIPE dropbear doesn't implement this, so ./dbclient localhost cat /dev/urandom | /bin/true runs forever. e...@openssh.com is specified here: http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL?rev=HEAD;content-type=text/plain (section 2.1) I have a draft implementation of this in dropbear (attached), but there is one significant issue: In cli-session.c, stdin, stdout and stderr are dup()'ed in order to be able to restore file flags at the end of the session. This means that if the client gets e...@openssh.com from the server and close(0), this is actually not the last outstanding ref to the pipe. There's still an fd 4 or so, which means the writer actually doesn't see EPIPE. So a case like this is still broken: producer | ./dbclient host remote command that closes stdin On my ubuntu dev machine I could just comment the dup()/flags hack out, which made this work. But I'm not sure whether this is really still needed at all. What is the history behind this? The comment says: /* We store std{in,out,err}'s flags, so we can set them back on exit * (otherwise busybox's ash isn't happy */ but that's not much detail and I'm not sure if it's really still needed.
implementing e...@openssh.com
e...@openssh.com is an extension that allows EPIPE to propagate through SSH sessions. For example: ssh localhost cat /dev/urandom | /bin/true will very quickly exit because /bin/true does not consume its stdin. The mechanism is: - /bin/true calls exit(0), closing the last remaining ref to its stdin pipe - ssh tries to write() and gets EPIPE - ssh sends e...@openssh.com channel request to server - sshd handles e...@openssh.com by closing read side of its pipe - 'cat /etc/urandom' itself tries to write(), sees EPIPE and is killed by SIGPIPE dropbear doesn't implement this, so ./dbclient localhost cat /dev/urandom | /bin/true runs forever. e...@openssh.com is specified here: http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL?rev=HEAD;content-type=text/plain (section 2.1) I have a draft implementation of this in dropbear (attached), but there is one significant issue: In cli-session.c, stdin, stdout and stderr are dup()'ed in order to be able to restore file flags at the end of the session. This means that if the client gets e...@openssh.com from the server and close(0), this is actually not the last outstanding ref to the pipe. There's still an fd 4 or so, which means the writer actually doesn't see EPIPE. So a case like this is still broken: producer | ./dbclient host remote command that closes stdin On my ubuntu dev machine I could just comment the dup()/flags hack out, which made this work. But I'm not sure whether this is really still needed at all. What is the history behind this? The comment says: /* We store std{in,out,err}'s flags, so we can set them back on exit * (otherwise busybox's ash isn't happy */ but that's not much detail and I'm not sure if it's really still needed. dropbear-eow.patch Description: Binary data
Re: dbclient half-close?
Maybe the check on common-channel.c:338 should be against writefd instead of readfd? This would get set by close_chan_fd(channel-writefd) once recv_eof happens. This patch indeed causes 'foo' to surface after input EOF: diff -r 69cb561cc4c4 common-channel.c --- a/common-channel.c Sat Jul 13 11:53:24 2013 +0300 +++ b/common-channel.c Sat Jul 13 12:50:41 2013 +0300 @@ -335,7 +335,7 @@ } /* And if we can't receive any more data from them either, close up */ - if (channel-readfd == FD_CLOSED + if (channel-writefd == FD_CLOSED (ERRFD_IS_WRITE(channel) || channel-errfd == FD_CLOSED) !channel-sent_close close_allowed On Sat, Jul 13, 2013 at 12:31 PM, Catalin Patulea c...@vv.carleton.ca wrote: Hi, I'm seeing a difference in how dbclient handles EOF on input compared to openssh client. openssh client propagates input EOF to the remote command, but continues pumping command stdout. dbclient seems to abort before flushing the stdout buffer. In the following examples, 1.2.3.4 is an openwrt router running dropbear server. The remote command is designed to wait for EOF, then output something to stdout. openssh client: $ ssh root@1.2.3.4 'cat; echo foo' ^D foo dbclient: $ ./dbclient root@1.2.3.4 'cat; echo foo' ^D no output I build dropbear with DEBUG_TRACE and these are the last few lines: TRACE (...): empty queue dequeing ^D TRACE (...): send normal readfd TRACE (...): enter send_msg_channel_data TRACE (...): enter send_msg_channel_data isextended 0 fd 0 TRACE (...): maxlen 16375 TRACE (...): CLOSE some fd 0 TRACE (...): leave send_msg_channel_data: len 0 read err 17 or EOF for fd 0 TRACE (...): enter send_msg_channel_eof TRACE (...): leave send_msg_channel_eof TRACE (...): sending close, readfd is closed TRACE (...): enter send_msg_channel_close 0xcbfdc0 TRACE (...): enter cli_tty_cleanup TRACE (...): leave cli_tty_cleanup: not in raw mode TRACE (...): CLOSE some fd -1 TRACE (...): CLOSE some fd 2 I tried reading through the relevant sections of channel-common.c but I could use some guidance/background. Is this behaviour intentional? Catalin