[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 |