Skip to content

Commit

Permalink
add -J proxyjump option (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
upa committed Apr 14, 2024
1 parent e47d5b7 commit abfd91a
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 7 deletions.
16 changes: 16 additions & 0 deletions doc/mscp.1.in
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ mscp \- copy files over multiple SSH connections
.BI \-i \ IDENTITY\c
]
[\c
.BI \-J \ DESTINATION\c
]
[\c
.BI \-c \ CIPHER\c
]
[\c
Expand Down Expand Up @@ -270,6 +273,19 @@ supports.
.B \-i \fIIDENTITY\fR
Specifies the identity file for public key authentication.

.TP
.B \-J \fIDESTINATION\fR
A shortcut to define a
.B ProxyJump
configuration directive. Each SFTP session of
.B mscp
connects to the target host by first making an
.B ssh
connection to the jump host described by
.I destination.



.TP
.B \-c \fICIPHER\fR
Selects the cipher to use for encrypting the data transfer. See
Expand Down
11 changes: 8 additions & 3 deletions doc/mscp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
MSCP
====

:Date: v0.1.5-16-ga1ba6f1
:Date: v0.1.5-18-ge47d5b7

NAME
====
Expand All @@ -18,8 +18,8 @@ SYNOPSIS
**-S** *MAX_CHUNK_SIZE* ] [ **-a** *NR_AHEAD* ] [ **-b** *BUF_SIZE* ] [
**-L** *LIMIT_BITRATE* ] [ **-l** *LOGIN_NAME* ] [ **-P** *PORT* ] [
**-F** *SSH_CONFIG* ] [ **-o** *SSH_OPTION* ] [ **-i** *IDENTITY* ] [
**-c** *CIPHER* ] [ **-M** *HMAC* ] [ **-C** *COMPRESS* ] [ **-g**
*CONGESTION* ] *source ... target*
**-J** *DESTINATION* ] [ **-c** *CIPHER* ] [ **-M** *HMAC* ] [ **-C**
*COMPRESS* ] [ **-g** *CONGESTION* ] *source ... target*

DESCRIPTION
===========
Expand Down Expand Up @@ -159,6 +159,11 @@ OPTIONS
**-i IDENTITY**
Specifies the identity file for public key authentication.

**-J DESTINATION**
A shortcut to define a **ProxyJump** configuration directive. Each
SFTP session of **mscp** connects to the target host by first making
an **ssh** connection to the jump host described by *destination.*

**-c CIPHER**
Selects the cipher to use for encrypting the data transfer. See
`libssh features <https://www.libssh.org/features/>`__.
Expand Down
1 change: 1 addition & 0 deletions include/mscp.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ struct mscp_ssh_opts {
char *config; /** path to ssh_config, default ~/.ssh/config*/
char **options; /** array of ssh_config options, terminated by NULL */
char *identity; /** path to private key */
char *proxyjump; /** ProxyJump configuration directive (shortcut) */
char *cipher; /** cipher spec */
char *hmac; /** hmacp spec */
char *compress; /** yes, no, zlib@openssh.com */
Expand Down
3 changes: 3 additions & 0 deletions scripts/test-in-container.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ set -x
echo "Port 22" >> /etc/ssh/sshd_config
echo "Port 8022" >> /etc/ssh/sshd_config

## Alpine default sshd disables TcpForwarding, which is required for proxyjump test
echo "AllowTcpForwarding yes" >> /etc/ssh/sshd_config.d/10-accept-tcp-forwarding.conf

# Run sshd
if [ ! -e /var/run/sshd.pid ]; then
/usr/sbin/sshd
Expand Down
12 changes: 8 additions & 4 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ void usage(bool print_help)
{
printf("mscp " MSCP_BUILD_VERSION ": copy files over multiple SSH connections\n"
"\n"
"Usage: mscp [-46vqDpdNh] [-n nr_conns] [-m coremask]\n"
" [-u max_startups] [-I interval] [-W checkpoint] [-R checkpoint]\n"
"Usage: mscp [-46vqDpdNh] [-n nr_conns] [-m coremask] [-u max_startups]\n"
" [-I interval] [-W checkpoint] [-R checkpoint]\n"
" [-s min_chunk_sz] [-S max_chunk_sz] [-a nr_ahead]\n"
" [-b buf_sz] [-L limit_bitrate]\n"
" [-l login_name] [-P port] [-F ssh_config] [-o ssh_option]\n"
" [-i identity_file] [-c cipher_spec] [-M hmac_spec]\n"
" [-i identity_file] [-J destination] [-c cipher_spec] [-M hmac_spec]\n"
" [-C compress] [-g congestion]\n"
" source ... target\n"
"\n");
Expand Down Expand Up @@ -64,6 +64,7 @@ void usage(bool print_help)
" -F SSH_CONFIG path to user ssh config (default ~/.ssh/config)\n"
" -o SSH_OPTION ssh_config option\n"
" -i IDENTITY identity file for public key authentication\n"
" -J DESTINATION ProxyJump destination\n"
" -c CIPHER cipher spec\n"
" -M HMAC hmac spec\n"
" -C COMPRESS enable compression: "
Expand Down Expand Up @@ -277,7 +278,7 @@ int main(int argc, char **argv)
memset(&o, 0, sizeof(o));
o.severity = MSCP_SEVERITY_WARN;

#define mscpopts "n:m:u:I:W:R:s:S:a:b:L:46vqDrl:P:i:F:o:c:M:C:g:pdNh"
#define mscpopts "n:m:u:I:W:R:s:S:a:b:L:46vqDrl:P:F:o:i:J:c:M:C:g:pdNh"
while ((ch = getopt(argc, argv, mscpopts)) != -1) {
switch (ch) {
case 'n':
Expand Down Expand Up @@ -375,6 +376,9 @@ int main(int argc, char **argv)
case 'i':
s.identity = optarg;
break;
case 'J':
s.proxyjump = optarg;
break;
case 'c':
s.cipher = optarg;
break;
Expand Down
10 changes: 10 additions & 0 deletions src/ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,16 @@ static int ssh_set_opts(ssh_session ssh, struct mscp_ssh_opts *opts)
return -1;
}

if (opts->proxyjump) {
char buf[256];
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf), "proxyjump=%s", opts->proxyjump);
if (ssh_config_parse_string(ssh, buf) != SSH_OK) {
priv_set_errv("failed to set ssh option: %s", buf);
return -1;
}
}

if (opts->options) {
int n;
for (n = 0; opts->options[n]; n++) {
Expand Down
25 changes: 25 additions & 0 deletions test/test_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,31 @@ def test_inline_option_ng(mscp, src_prefix, dst_prefix, option):
src.cleanup()


@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
def test_porxyjump_ok(mscp, src_prefix, dst_prefix):
""" test -J proxyjump option"""
src = File("src", size = 10 * 1024 * 1024).make()
dst = File("dst")
# use small min-chunk-size to use multiple connections
run2ok([mscp, "-n", 4, "-s", 1024 * 1024, "-vvv",
"-J", "localhost:8022",
src_prefix + src.path, dst_prefix + dst.path])
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()


@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
def test_porxyjump_ng(mscp, src_prefix, dst_prefix):
""" test -J proxyjump option, invalid jump node causes fail"""
src = File("src", size = 10 * 1024 * 1024).make()
dst = File("dst")
# use small min-chunk-size to use multiple connections
run2ng([mscp, "-n", 4, "-s", 1024 * 1024, "-vvv",
"-J", "invaliduser@localhost:8022",
src_prefix + src.path, dst_prefix + dst.path])
src.cleanup()

# username test assumes that this test runs inside a container, see Dockerfiles
def test_specify_passphrase_via_env(mscp):
src = File(os.getcwd() + "/src", size = 1024).make()
Expand Down

0 comments on commit abfd91a

Please sign in to comment.