1#!/usr/bin/perl 2# $OpenBSD: remote.pl,v 1.9 2016/08/25 22:56:13 bluhm Exp $ 3 4# Copyright (c) 2010-2014 Alexander Bluhm <bluhm@openbsd.org> 5# 6# Permission to use, copy, modify, and distribute this software for any 7# purpose with or without fee is hereby granted, provided that the above 8# copyright notice and this permission notice appear in all copies. 9# 10# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 18use strict; 19use warnings; 20use File::Basename; 21use File::Copy; 22use Socket; 23use Socket6; 24 25use Client; 26use Relayd; 27use Server; 28use Remote; 29require 'funcs.pl'; 30 31sub usage { 32 die <<"EOF"; 33usage: 34 remote.pl localport remoteaddr remoteport [test-args.pl] 35 Run test with local client and server. Remote relayd 36 forwarding from remoteaddr remoteport to server localport 37 has to be started manually. 38 remote.pl copy|splice listenaddr connectaddr connectport [test-args.pl] 39 Only start remote relayd. 40 remote.pl copy|splice localaddr remoteaddr remotessh [test-args.pl] 41 Run test with local client and server. Remote relayd is 42 started automatically with ssh on remotessh. 43EOF 44} 45 46my $testfile; 47our %args; 48if (@ARGV and -f $ARGV[-1]) { 49 $testfile = pop; 50 do $testfile 51 or die "Do test file $testfile failed: ", $@ || $!; 52} 53my $mode = 54 @ARGV == 3 && $ARGV[0] =~ /^\d+$/ && $ARGV[2] =~ /^\d+$/ ? "manual" : 55 @ARGV == 4 && $ARGV[1] !~ /^\d+$/ && $ARGV[3] =~ /^\d+$/ ? "relay" : 56 @ARGV == 4 && $ARGV[1] !~ /^\d+$/ && $ARGV[3] !~ /^\d+$/ ? "auto" : 57 usage(); 58 59my($s, $r, $c); 60if ($mode eq "relay") { 61 my($rport) = find_ports(num => 1); 62 $r = Relayd->new( 63 forward => $ARGV[0], 64 %{$args{relayd}}, 65 listendomain => AF_INET, 66 listenaddr => $ARGV[1], 67 listenport => $rport, 68 connectdomain => AF_INET, 69 connectaddr => $ARGV[2], 70 connectport => $ARGV[3], 71 logfile => dirname($0)."/remote.log", 72 conffile => dirname($0)."/relayd.conf", 73 testfile => $testfile, 74 ); 75 open(my $log, '<', $r->{logfile}) 76 or die "Remote log file open failed: $!"; 77 $SIG{__DIE__} = sub { 78 die @_ if $^S; 79 copy($log, \*STDERR); 80 warn @_; 81 exit 255; 82 }; 83 copy($log, \*STDERR); 84 $r->run; 85 copy($log, \*STDERR); 86 $r->up; 87 copy($log, \*STDERR); 88 print STDERR "listen sock: $ARGV[1] $rport\n"; 89 <STDIN>; 90 copy($log, \*STDERR); 91 print STDERR "stdin closed\n"; 92 $r->kill_child; 93 $r->down; 94 copy($log, \*STDERR); 95 96 exit; 97} 98 99my $redo = $args{lengths} && @{$args{lengths}}; 100$redo = 0 if $args{client}{http_vers}; # run only one persistent connection 101$s = Server->new( 102 forward => $ARGV[0], 103 func => \&read_char, 104 redo => $redo, 105 %{$args{server}}, 106 listendomain => AF_INET, 107 listenaddr => ($mode eq "auto" ? $ARGV[1] : undef), 108 listenport => ($mode eq "manual" ? $ARGV[0] : undef), 109 testfile => $testfile, 110 client => \$c, 111) unless $args{server}{noserver}; 112if ($mode eq "auto") { 113 $r = Remote->new( 114 forward => $ARGV[0], 115 logfile => "relayd.log", 116 %{$args{relayd}}, 117 remotessh => $ARGV[3], 118 listenaddr => $ARGV[2], 119 connectaddr => $ARGV[1], 120 connectport => $s ? $s->{listenport} : 1, 121 testfile => $testfile, 122 ); 123 $r->run->up; 124} 125$c = Client->new( 126 forward => $ARGV[0], 127 func => \&write_char, 128 %{$args{client}}, 129 connectdomain => AF_INET, 130 connectaddr => ($mode eq "manual" ? $ARGV[1] : $r->{listenaddr}), 131 connectport => ($mode eq "manual" ? $ARGV[2] : $r->{listenport}), 132 testfile => $testfile, 133 server => \$s, 134) unless $args{client}{noclient}; 135 136$s->run unless $args{server}{noserver}; 137$c->run->up unless $args{client}{noclient}; 138$s->up unless $args{server}{noserver}; 139 140$c->down unless $args{client}{noclient}; 141$s->down unless $args{server}{noserver}; 142$r->close_child; 143$r->down; 144 145check_logs($c, $r, $s, %args); 146