[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [patch]: Stop connector socket-to-channel EOF flooding
[Thread Prev] | [Thread Next]
- Subject: Re: [patch]: Stop connector socket-to-channel EOF flooding
- From: g4-lisz@xxxxxxxxxxxx
- Reply-to: libssh@xxxxxxxxxx
- Date: Mon, 8 Apr 2019 20:54:09 +0200
- To: libssh@xxxxxxxxxx
- Cc: Andreas Schneider <asn@xxxxxxxxxxxxxx>
On 01.04.19 13:29, g4-lisz@xxxxxxxxxxxx wrote: > Hi there, > > I'm using connectors for a direct-tcp client. So this creates two > connectors FD in --> channel out and vice versa. > > Now when the socket forwarding peer (not the ssh server) closes the > connection, i.e. reading on the socket returns 0 = EOF, we end up in > some loop with sending EOFs on the channel, until finally the client > receives a channel close message. > I attached some test code to reproduce this. Edit line 14 to your needs. It should connect to a service which does not dicsonnecet the connenction from its side. I.e. SSH is fine. A webserver will not do because it disconnects after answering the request. Start a local sshd with shell1> /usr/sbin/sshd -d -d -p 2222 shell2> ./fwconnector username localhost 2222 shell3> ssh admin@localhost -p 2022 Welcome to Debian... ~: exit On shell1 you will see the > 20 lines of "channel 0: rcvd eof" Cheers, Till
#include <libssh/libssh.h> #include <libssh/callbacks.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/time.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> const char *remote_desthost = "mysshserver.com"; /* resolved by the remote server */ int remote_destport = 22; const char *local_listenip = "127.0.0.1"; int local_listenport = 2022; char *ssh_host; int ssh_port; char *ssh_user; static void channel_eof_cb(ssh_session session, ssh_channel channel, void *userdata) { (void) userdata; printf("Channel got EOF.\n"); ssh_channel_send_eof(channel); } static void select_loop(ssh_session session, ssh_channel channel, int fd) { ssh_connector connector_in, connector_out, connector_err; struct ssh_channel_callbacks_struct cb = { .channel_eof_function = channel_eof_cb }; ssh_callbacks_init(&cb); ssh_set_channel_callbacks(channel, &cb); ssh_event event = ssh_event_new(); /* stdin */ connector_in = ssh_connector_new(session); ssh_connector_set_out_channel(connector_in, channel, SSH_CONNECTOR_STDOUT); ssh_connector_set_in_fd(connector_in, fd); ssh_event_add_connector(event, connector_in); /* stdout */ connector_out = ssh_connector_new(session); ssh_connector_set_out_fd(connector_out, fd); ssh_connector_set_in_channel(connector_out, channel, SSH_CONNECTOR_STDOUT); ssh_event_add_connector(event, connector_out); /* stderr */ /*connector_err = ssh_connector_new(session); ssh_connector_set_out_fd(connector_err, 2); ssh_connector_set_in_channel(connector_err, channel, SSH_CONNECTOR_STDERR); ssh_event_add_connector(event, connector_err);*/ while (ssh_channel_is_open(channel)) { ssh_event_dopoll(event, 5000); printf("Loop alive - ssh_channel_is_eof: %d\n", ssh_channel_is_eof(channel)); } ssh_event_remove_connector(event, connector_in); ssh_event_remove_connector(event, connector_out); //ssh_event_remove_connector(event, connector_err); ssh_connector_free(connector_in); ssh_connector_free(connector_out); //ssh_connector_free(connector_err); ssh_event_free(event); } int forward_tunnel(ssh_session session) { struct sockaddr_in sin; int listensock = -1; int forwardsock = -1; unsigned sout_len = 0; ssh_channel channel; int rc; listensock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (listensock == -1) { fprintf(stderr, "Error creating socket\n"); goto shutdown; } sin.sin_family = AF_INET; sin.sin_port = htons(local_listenport); if (INADDR_NONE == (sin.sin_addr.s_addr = inet_addr(local_listenip))) { fprintf(stderr, "Invalid local IP address\n"); goto shutdown; } if (-1 == bind(listensock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in))) { perror("Failed to connect"); goto shutdown; } if (-1 == listen(listensock,1)) { perror("Failed to listen"); goto shutdown; } fprintf(stdout, "Accepting connections on %s:%d\n", local_listenip, local_listenport); /* Setting session to non-blocking IO */ //ssh_set_blocking(session, 0); while(1) { sout_len = 0; forwardsock = accept(listensock, NULL, &sout_len); if (forwardsock < 0) { perror("accept failed"); continue; } channel = ssh_channel_new(session); if (channel == NULL) { fprintf(stderr, "Couldn't allocate channel: %s\n", ssh_get_error(session)); close(forwardsock); continue; } fprintf(stdout, "Forwarding connection on remote %s:%d to %s:%d\n", remote_desthost, remote_destport, local_listenip, local_listenport); rc = ssh_channel_open_forward(channel, remote_desthost, remote_destport, local_listenip, local_listenport); if (rc != SSH_OK) { fprintf(stderr, "Couldn't open forwarding channel %d: %s\n", rc, ssh_get_error(session)); goto shutdown; } //ssh_channel_set_blocking(channel, 1); select_loop(session, channel, forwardsock); //ssh_channel_set_blocking(channel, 0); ssh_channel_free(channel); close(forwardsock); fprintf(stdout, "New round\n"); } shutdown: close(listensock); return rc; } int main(int argc, char **argv) { ssh_session my_ssh_session; int verbosity = SSH_LOG_FUNCTIONS; int rc; if (argc < 4) { printf("Usage: %s <user> <host> <port>\n", argv[0]); exit(0); } ssh_user = argv[1]; ssh_host = argv[2]; ssh_port = atoi(argv[3]); my_ssh_session = ssh_new(); if (my_ssh_session == NULL) exit(-1); ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, ssh_host); ssh_options_set(my_ssh_session, SSH_OPTIONS_USER, ssh_user); ssh_options_set(my_ssh_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &ssh_port); rc = ssh_connect(my_ssh_session); if (rc != SSH_OK) { fprintf(stderr, "Error connecting to localhost: %s\n", ssh_get_error(my_ssh_session)); goto finish; } printf("We are connected.\n"); rc = ssh_userauth_publickey_auto(my_ssh_session, NULL, NULL); if (rc != SSH_AUTH_SUCCESS) { fprintf(stderr, "Authentication failed: %s\n", ssh_get_error(my_ssh_session)); goto finish; } printf("We are authenticated.\n"); forward_tunnel(my_ssh_session); finish: ssh_disconnect(my_ssh_session); ssh_free(my_ssh_session); }
Re: [patch]: Stop connector socket-to-channel EOF flooding | Tilo Eckert <tilo.eckert@xxxxxxx> |
[patch]: Stop connector socket-to-channel EOF flooding | g4-lisz@xxxxxxxxxxxx |