et_client.pl 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #!/usr/bin/perl
  2. # et_server/et_client: an "ssh -Rport" replacement.
  3. # Problem: webserver is behind a firewall without the possibility of opening a
  4. # hole in th firewall. Solution: start et_server on a publicly available host,
  5. # and connect to it via et_client from inside of the firewall.
  6. use warnings;
  7. use strict;
  8. use IO::Socket;
  9. die "Usage: et_client.pl et_serverhost:Port localhost:Port\n"
  10. if(int(@ARGV) != 2);
  11. my $cfd = IO::Socket::INET->new(PeerAddr=>$ARGV[0]);
  12. die "Opening port $ARGV[0]: $!\n" if(!$cfd);
  13. my %clients;
  14. for(;;) {
  15. my ($rin,$rout) = ('','');
  16. vec($rin, $cfd->fileno(), 1) = 1;
  17. foreach my $c (keys %clients) {
  18. vec($rin, fileno($clients{$c}{fd}), 1) = 1;
  19. }
  20. my $nfound = select($rout=$rin, undef, undef, undef);
  21. if($nfound < 0) {
  22. print("select: $!");
  23. last;
  24. }
  25. # New et-line request
  26. if(vec($rout, $cfd->fileno(), 1)) {
  27. my $buf;
  28. my $ret = sysread($cfd, $buf, 1);
  29. if(!defined($ret) || $ret <= 0) {
  30. print "ET_Server left us\n";
  31. exit(1);
  32. }
  33. my $fd1 = IO::Socket::INET->new(PeerAddr=>$ARGV[0]);
  34. if(!$fd1) {
  35. print "Connect to $ARGV[0] failed";
  36. exit(1);
  37. }
  38. $fd1->setsockopt(SOL_SOCKET, SO_KEEPALIVE, 1);
  39. my $fd2 = IO::Socket::INET->new(PeerAddr=>$ARGV[1]);
  40. if(!$fd2) {
  41. print "Connect to $ARGV[1] failed";
  42. exit(1);
  43. }
  44. $fd2->setsockopt(SOL_SOCKET, SO_KEEPALIVE, 1);
  45. $clients{$fd1}{fd} = $fd1;
  46. $clients{$fd2}{fd} = $fd2;
  47. $clients{$fd1}{peer} = $fd2;
  48. $clients{$fd2}{peer} = $fd1;
  49. $clients{$fd1}{type} = "ET";
  50. $clients{$fd2}{type} = "LC";
  51. print "ET line established\n";
  52. }
  53. # Data from one of the clients
  54. CLIENT:foreach my $c (keys %clients) {
  55. my $fno = fileno($clients{$c}{fd});
  56. next if(!vec($rout, $fno, 1));
  57. my $peer = $clients{$c}{peer};
  58. my $buf;
  59. my $ret = sysread($clients{$c}{fd}, $buf, 256);
  60. #print "$c: $ret\n";
  61. if(!defined($ret) || $ret <= 0) {
  62. print "Client $fno left us ($clients{$c}{type})\n";
  63. if($peer) {
  64. close($clients{$peer}{fd}); delete($clients{$peer});
  65. }
  66. close($clients{$c}{fd}); delete($clients{$c});
  67. last CLIENT;
  68. }
  69. while(length($buf)) {
  70. my $ret = syswrite($clients{$peer}{fd}, $buf);
  71. if(!$ret) {
  72. print "Write error to peer of $fno ($clients{$c}{type})\n";
  73. close($clients{$peer}{fd}); delete($clients{$peer});
  74. close($clients{$c}{fd}); delete($clients{$c});
  75. last CLIENT;
  76. }
  77. $buf = substr($buf, $ret);
  78. }
  79. }
  80. }