-
-
Save aszlig/5e8c8462d17f787b7f171c34090fd590 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ debug ? false }: | |
let | |
pinnedNixpkgs = let | |
rev = "2839b101f927be5daab7948421de00a6f6c084ae"; | |
url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz"; | |
in fetchTarball url; | |
in import "${pinnedNixpkgs}/nixos/tests/make-test.nix" ({ pkgs, lib, ... }: { | |
name = "test-openssh-tun"; | |
nodes = let | |
snakeoilKeyPair = import (pkgs.runCommand "snakeoil-keypair.nix" { | |
buildInputs = [ pkgs.openssh ]; | |
} '' | |
ssh-keygen -t ed25519 -f key -N "" -C snakeoil-key | |
transform='$! { :l; N; $!bl; }; s/["\\$]/\\&/g; s/\n/\\n/g; p' | |
( echo "{" | |
echo " privateKey = \"$(sed -n -e "$transform" key)\\n\";" | |
echo " publicKey = \"$(sed -n -e "$transform" key.pub)\";" | |
echo "}" | |
) > "$out" | |
''); | |
common = { config, pkgs, ... }: { | |
boot.kernelModules = [ "tun" ]; | |
networking.firewall.enable = false; | |
environment.systemPackages = [ config.boot.kernelPackages.perf ]; | |
nixpkgs.config.packageOverrides = super: { | |
openssh = super.openssh.overrideDerivation (drv: { | |
patches = (drv.patches or []) ++ [ ./openssh-verbose.patch ]; | |
}); | |
}; | |
}; | |
client = { | |
imports = [ common ]; | |
environment.etc.snakeoil = { | |
text = snakeoilKeyPair.privateKey; | |
mode = "0600"; | |
}; | |
}; | |
server = { config, ... }: { | |
imports = [ common ]; | |
services.openssh.enable = true; | |
services.openssh.extraConfig = '' | |
${lib.optionalString debug "LogLevel DEBUG3"} | |
PermitTunnel yes | |
''; | |
users.users.root.openssh.authorizedKeys = { | |
keys = lib.singleton snakeoilKeyPair.publicKey; | |
}; | |
}; | |
oldKernel.boot.kernelPackages = pkgs.linuxPackages_4_4; | |
in { | |
oldclient.imports = [ client oldKernel ]; | |
oldserver.imports = [ server oldKernel ]; | |
newclient = client; | |
newserver = server; | |
}; | |
testScript = { nodes, ... }: let | |
localCommand = lib.concatStringsSep " && " [ | |
"ip addr add 1.1.1.1/32 peer 2.2.2.2 dev tun1000" | |
"ip link set tun1000 up" | |
]; | |
remoteCommand = lib.concatStringsSep " && " [ | |
"ip addr add 2.2.2.2/32 peer 1.1.1.1 dev tun2000" | |
"ip link set tun2000 up" | |
]; | |
perfie = pkgs.writeScript "perfie.sh" '' | |
#!${pkgs.stdenv.shell} | |
while [ ! -e /tmp/stop_perf ]; do sleep 1; done | |
touch /tmp/perf_stopped | |
''; | |
collectPerf = node: '' | |
''$${node}->execute('touch /tmp/stop_perf'); | |
''$${node}->waitForFile('/tmp/perf_stopped'); | |
''$${node}->execute('perf script >&2'); | |
''; | |
startupAll = "startAll;" + lib.concatMapStrings (node: '' | |
''$${node}->waitForUnit('multi-user.target'); | |
''$${node}->execute('ip monitor all >&2 &'); | |
''$${node}->execute('perf probe -a dev_close >&2'); | |
''$${node}->execute('perf record -a -R -g -e probe:* ${perfie} >&2 &'); | |
'') (lib.attrNames nodes); | |
in startupAll + lib.concatMapStrings (prefix: let | |
client = "${prefix}client"; | |
server = "${prefix}server"; | |
kver = nodes.${client}.config.boot.kernelPackages.kernel.version; | |
perlEscape = lib.escape ["'"]; | |
mkCmd = x: perlEscape (lib.concatMapStringsSep " " lib.escapeShellArg x); | |
execSSH = args: mkCmd ([ "ssh" ] ++ lib.optional debug "-vvv" ++ args); | |
in '' | |
subtest "checking with kernel version ${kver}", sub { | |
''$${client}->succeed('${execSSH [ | |
"-i" "/etc/snakeoil" | |
"-o" "StrictHostKeyChecking=no" | |
"-o" "PermitLocalCommand=yes" | |
"-o" "LocalCommand=${localCommand}" | |
"-w" "1000:2000" | |
server remoteCommand | |
]} >&2 & perf trace -p $! >&2 &'); | |
''$${client}->waitUntilSucceeds('ip link show tun1000'); | |
''$${client}->sleep(5); | |
''$${client}->execute('ip link list >&2'); | |
''$${server}->execute('ip link list >&2'); | |
''$${client}->succeed('ping -c1 -s 512 2.2.2.2'); | |
''$${server}->succeed('ping -c1 -s 512 1.1.1.1'); | |
}; | |
${collectPerf client} | |
${collectPerf server} | |
''$${client}->crash; | |
''$${server}->crash; | |
'') [ "old" "new" ]; | |
}) {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/channels.c b/channels.c | |
index 398da9a8..e3519997 100644 | |
--- a/channels.c | |
+++ b/channels.c | |
@@ -1734,6 +1734,8 @@ channel_handle_rfd(Channel *c, fd_set *readset, fd_set *writeset) | |
if (c->rfd != -1 && (force || FD_ISSET(c->rfd, readset))) { | |
errno = 0; | |
len = read(c->rfd, buf, sizeof(buf)); | |
+ debug("channel %d read() returned %d, errno: %d", | |
+ c->self, len, errno); | |
if (len < 0 && (errno == EINTR || | |
((errno == EAGAIN || errno == EWOULDBLOCK) && !force))) | |
return 1; | |
@@ -1805,6 +1807,8 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset) | |
if (c->datagram) { | |
/* ignore truncated writes, datagrams might get lost */ | |
len = write(c->wfd, buf, dlen); | |
+ debug("channel %d write() returned %d, errno: %d", | |
+ c->self, len, errno); | |
free(data); | |
if (len < 0 && (errno == EINTR || errno == EAGAIN || | |
errno == EWOULDBLOCK)) | |
@@ -1825,6 +1829,8 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset) | |
#endif | |
len = write(c->wfd, buf, dlen); | |
+ debug("channel %d write() returned %d, errno: %d", | |
+ c->self, len, errno); | |
if (len < 0 && | |
(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) | |
return 1; | |
diff --git a/openbsd-compat/port-tun.c b/openbsd-compat/port-tun.c | |
index a444adf1..bd0387c7 100644 | |
--- a/openbsd-compat/port-tun.c | |
+++ b/openbsd-compat/port-tun.c | |
@@ -194,6 +194,23 @@ sys_tun_open(int tun, int mode) | |
} | |
#endif /* SSH_TUN_FREEBSD */ | |
+static void print_hex(u_char *buf, int len) | |
+{ | |
+ int chars = 0, bpos = 0; | |
+ char pbuf[4096]; | |
+ for (int i = 0; i < len; i++) { | |
+ snprintf(pbuf + bpos, 4096, "%02X ", *buf++); | |
+ bpos += 3; | |
+ if (++chars == 16 || i == len - 1) { | |
+ pbuf[bpos - 1] = '\0'; | |
+ debug("> %s", pbuf); | |
+ bpos = 0; | |
+ pbuf[0] = '\0'; | |
+ chars = 0; | |
+ } | |
+ } | |
+} | |
+ | |
/* | |
* System-specific channel filters | |
*/ | |
@@ -213,6 +230,9 @@ sys_tun_infilter(struct Channel *c, char *buf, int len) | |
char *ptr = buf; | |
int r; | |
+ debug("%d bytes from tun device to SSH channel:", len); | |
+ print_hex(buf, len); | |
+ | |
#if defined(SSH_TUN_PREPEND_AF) | |
if (len <= 0 || len > (int)(sizeof(rbuf) - sizeof(*af))) | |
return (-1); | |
@@ -277,6 +297,9 @@ sys_tun_outfilter(struct Channel *c, u_char **data, u_int *dlen) | |
*af = htonl(AF_INET); | |
#endif | |
+ debug("%d bytes from SSH channel to tun device:", *dlen); | |
+ print_hex(buf, *dlen); | |
+ | |
return (buf); | |
} | |
#endif /* SSH_TUN_FILTER */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment