@@ -278,7 +278,7 @@ static void client_bootstrap(struct tmate_session *_session)
278
278
/* never reached */
279
279
}
280
280
281
- static int get_client_ip (int fd , char * dst , size_t len )
281
+ static int get_client_ip_socket (int fd , char * dst , size_t len )
282
282
{
283
283
struct sockaddr sa ;
284
284
socklen_t sa_len = sizeof (sa );
@@ -305,6 +305,62 @@ static int get_client_ip(int fd, char *dst, size_t len)
305
305
return 0 ;
306
306
}
307
307
308
+ static void read_single_line (int fd , char * dst , size_t len )
309
+ {
310
+ /*
311
+ * This reads exactly one line from fd.
312
+ * We cannot read bytes after the new line.
313
+ * We could use recv() with MSG_PEEK to do this more efficiently.
314
+ */
315
+ for (size_t i = 0 ; i < len ; i ++ ) {
316
+ if (read (fd , & dst [i ], 1 ) <= 0 )
317
+ break ;
318
+
319
+ if (dst [i ] == '\r' )
320
+ i -- ;
321
+
322
+ if (dst [i ] == '\n' ) {
323
+ dst [i ] = '\0' ;
324
+ return ;
325
+ }
326
+ }
327
+
328
+ tmate_fatal ("Cannot read proxy header. Load balancer may be misconfigured" );
329
+ }
330
+
331
+ static int get_client_ip_proxy_protocol (int fd , char * dst , size_t len )
332
+ {
333
+ char header [110 ];
334
+ const char * signature = "PROXY " ;
335
+
336
+ if (read (fd , header , strlen (signature )) != (ssize_t )strlen (signature ))
337
+ tmate_fatal ("Cannot read proxy header" );
338
+
339
+ if (memcmp (header , signature , strlen (signature )))
340
+ tmate_fatal ("No proxy header found. Load balancer may be misconfigured" );
341
+
342
+ read_single_line (fd , header , sizeof (header ));
343
+
344
+ int tok_num = 0 ;
345
+ for (char * tok = strtok (header , " " ); tok ; tok = strtok (NULL , " " ), tok_num ++ ) {
346
+ if (tok_num == 1 )
347
+ strncpy (dst , tok , len );
348
+ }
349
+
350
+ if (tok_num != 5 )
351
+ tmate_fatal ("Proxy header is invalid" );
352
+
353
+ return 0 ;
354
+ }
355
+
356
+ static int get_client_ip (int fd , char * dst , size_t len )
357
+ {
358
+ if (tmate_settings -> use_proxy_protocol )
359
+ return get_client_ip_proxy_protocol (fd , dst , len );
360
+ else
361
+ return get_client_ip_socket (fd , dst , len );
362
+ }
363
+
308
364
static void ssh_log_function (int priority , const char * function ,
309
365
const char * buffer , __unused void * userdata )
310
366
{
@@ -426,7 +482,7 @@ void tmate_ssh_server_main(struct tmate_session *session, const char *keys_dir,
426
482
alarm (TMATE_SSH_GRACE_PERIOD );
427
483
428
484
if (get_client_ip (fd , client -> ip_address , sizeof (client -> ip_address )) < 0 )
429
- tmate_fatal ("Error getting Client IP from connection" );
485
+ tmate_fatal ("Error getting client IP from connection" );
430
486
431
487
tmate_info ("Connection accepted ip=%s" , client -> ip_address );
432
488
0 commit comments