Tentukan port yang dialokasikan secara dinamis untuk OpenSSH RemoteForward

13

Pertanyaan (TL; DR)

Ketika menetapkan port secara dinamis untuk penerusan jarak jauh ( -Ropsi alias ), bagaimana skrip pada mesin jarak jauh (misalnya bersumber dari .bashrc) menentukan port mana yang dipilih oleh OpenSSH?


Latar Belakang

Saya menggunakan OpenSSH (di kedua ujungnya) untuk terhubung ke server pusat kami, yang saya bagikan dengan banyak pengguna lain. Untuk sesi jarak jauh saya (untuk saat ini) saya ingin meneruskan X, gelas dan pulseaudio.

Yang paling sepele adalah meneruskan X, menggunakan -Xopsi. Alamat X yang dialokasikan disimpan dalam variabel lingkungan DISPLAYdan dari situ saya dapat menentukan port TCP yang sesuai, dalam banyak kasus, bagaimanapun juga. Tapi saya hampir tidak pernah perlu, karena kehormatan Xlib DISPLAY.

Saya perlu mekanisme serupa untuk cangkir dan pulseaudio. Dasar-dasar untuk kedua layanan ada , masing-masing dalam bentuk variabel lingkungan CUPS_SERVERdan PULSE_SERVER. Berikut adalah contoh penggunaan:

ssh -X -R12345:localhost:631 -R54321:localhost:4713 datserver

export CUPS_SERVER=localhost:12345
lowriter #and I can print using my local printer
lpr -P default -o Duplex=DuplexNoTumble minutes.pdf #printing through the tunnel
lpr -H localhost:631 -P default -o Duplex=DuplexNoTumble minutes.pdf #printing remotely

mpg123 mp3s/van_halen/jump.mp3 #annoy co-workers
PULSE_SERVER=localhost:54321 mpg123 mp3s/van_halen/jump.mp3 #listen to music through the tunnel

Masalahnya adalah pengaturan CUPS_SERVERdan PULSE_SERVERbenar.

Kami banyak menggunakan penerusan porta dan oleh karena itu saya memerlukan alokasi port dinamis. Alokasi port statis bukan merupakan opsi.

OpenSSH memiliki mekanisme untuk alokasi port dinamis pada server jarak jauh, dengan menetapkan 0sebagai port-bind untuk penerusan jarak jauh ( -Ropsi). Dengan menggunakan perintah berikut, OpenSSH akan secara dinamis mengalokasikan port untuk cangkir dan penerusan pulsa.

ssh -X -R0:localhost:631 -R0:localhost:4713 datserver

Ketika saya menggunakan perintah itu, sshakan mencetak yang berikut ke STDERR:

Allocated port 55710 for remote forward to 127.0.0.1:4713
Allocated port 41273 for remote forward to 127.0.0.1:631

Ada informasi yang saya inginkan! Pada akhirnya saya ingin menghasilkan:

export CUPS_SERVER=localhost:41273
export PULSE_SERVER=localhost:55710

Namun pesan "Alokasi port ..." dibuat di mesin lokal saya dan dikirim ke STDERR, yang saya tidak dapat mengaksesnya di mesin jarak jauh. Anehnya, OpenSSH tampaknya tidak memiliki sarana untuk mengambil informasi tentang penerusan porta.

Bagaimana cara mengambil informasi itu untuk dimasukkan ke dalam skrip shell untuk secara memadai mengatur CUPS_SERVERdan PULSE_SERVERpada host jarak jauh?


Jalan buntu

Satu-satunya hal mudah yang dapat saya temukan adalah meningkatkan verbositas sshdsampai informasi itu dapat dibaca dari log. Ini tidak layak karena informasi itu mengungkapkan lebih banyak informasi daripada yang dapat diakses oleh pengguna non-root.

Saya sedang berpikir tentang menambal OpenSSH untuk mendukung urutan pelarian tambahan yang mencetak representasi bagus dari struct internal permitted_opens, tetapi bahkan jika itu yang saya inginkan, saya masih tidak dapat mengakses skrip mengakses urutan pelarian klien dari sisi server.


Pasti ada cara yang lebih baik

Pendekatan berikut ini tampaknya sangat tidak stabil dan terbatas pada satu sesi SSH per pengguna. Namun, saya membutuhkan setidaknya dua sesi bersamaan dan pengguna lain bahkan lebih. Tapi saya mencoba ...

Ketika bintang-bintang disejajarkan dengan benar, setelah mengorbankan satu atau dua ayam, saya dapat menyalahgunakan fakta yang sshdtidak dimulai sebagai pengguna saya, tetapi menjatuhkan hak istimewa setelah login berhasil, untuk melakukan ini:

  • dapatkan daftar nomor port untuk semua soket mendengarkan milik pengguna saya

    netstat -tlpen | grep ${UID} | sed -e 's/^.*:\([0-9]\+\) .*$/\1/'

  • dapatkan daftar nomor port untuk semua soket mendengarkan yang menjadi milik proses pengguna saya mulai

    lsof -u ${UID} 2>/dev/null | grep LISTEN | sed -e 's/.*:\([0-9]\+\) (LISTEN).*$/\1/'

  • Semua port yang ada di set pertama, tetapi tidak di set kedua memiliki kemungkinan tinggi untuk menjadi port forwarding saya, dan memang mengurangi set hasil 41273, 55710dan 6010; cangkir, nadi dan X, masing-masing.

  • 6010diidentifikasi sebagai port X menggunakan DISPLAY.

  • 41273adalah port gelas, karena lpstat -h localhost:41273 -akembali 0.
  • 55710adalah port pulsa, karena pactl -s localhost:55710 statkembali 0. (Bahkan mencetak nama host klien saya!)

(Untuk melakukan set substraksi I sort -udan menyimpan output dari baris perintah di atas dan gunakan communtuk melakukan substraksi.)

Pulseaudio memungkinkan saya mengidentifikasi klien dan, untuk semua maksud dan tujuan, ini dapat berfungsi sebagai jangkar untuk memisahkan sesi SSH yang perlu dipisahkan. Namun, saya belum menemukan cara untuk mengikat 41273, 55710dan 6010ke sshdproses yang sama . netstattidak akan mengungkapkan informasi itu kepada pengguna non-root. Saya hanya mendapatkan -di PID/Program namekolom tempat saya ingin membaca 2339/54(dalam contoh khusus ini). Sangat dekat ...

Bananguin
sumber
fwiw, lebih akurat untuk mengatakan bahwa netstattidak akan menunjukkan PID untuk proses yang tidak Anda miliki atau ruang kernel. Misalnya
Bratchley
Cara paling kuat adalah menambal sshd ... Patch cepat & kotor hanya beberapa baris di tempat server mendapatkan port lokal dari OS, menulis nomor port ke file, nama yang dihasilkan dari pengguna, host jarak jauh dan Pelabuhan. Dengan asumsi server mengetahui port di sisi klien, yang tidak pasti, bahkan mungkin tidak mungkin (jika tidak, fitur sudah ada).
hyde
@ Hyde: tepatnya. Server jarak jauh tidak tahu tentang port yang diteruskan. Itu hanya membuat beberapa soket pendengaran dan data diteruskan melalui koneksi ssh. Tidak tahu tentang port tujuan lokal.
Bananguin

Jawaban:

1

Ambil dua (lihat histori untuk versi yang melakukan scp dari sisi server dan sedikit lebih sederhana), ini harus dilakukan. Intinya adalah ini:

  1. mengirimkan variabel lingkungan dari klien ke server, memberi tahu server bagaimana ia dapat mendeteksi kapan informasi port tersedia dan kemudian mendapatkan dan menggunakannya.
  2. begitu informasi port tersedia, salin dari klien ke server, memungkinkan server untuk mendapatkannya (dengan bantuan bagian 1 di atas), dan menggunakannya

Pertama, setup di sisi jarak jauh, Anda perlu mengaktifkan pengiriman variabel env dalam konfigurasi sshd :

sudo yourfavouriteeditor /etc/ssh/sshd_config

Temukan baris dengan AcceptEnvdan tambahkan MY_PORT_FILEpadanya (atau tambahkan baris di bawah Hostbagian kanan jika belum ada). Bagi saya garis menjadi ini:

AcceptEnv LANG LC_* MY_PORT_FILE

Juga ingat untuk memulai kembali sshd agar ini berlaku.

Selain itu, agar skrip di bawah ini berfungsi, lakukan mkdir ~/portfilesdi sisi yang jauh!


Kemudian di sisi lokal, potongan skrip yang akan

  1. buat nama file temp untuk pengarahan stderr
  2. tinggalkan pekerjaan latar belakang untuk menunggu file memiliki konten
  3. meneruskan nama file ke server sebagai variabel env, sementara mengarahkan ssh stderr ke file
  4. pekerjaan latar belakang hasil untuk menyalin file temp stderr ke sisi server menggunakan scp terpisah
  5. pekerjaan latar belakang juga menyalin file flag ke server untuk menunjukkan file stderr siap

Cuplikan skrip:

REMOTE=$USER@datserver

PORTFILE=`mktemp /tmp/sshdataserverports-$(hostname)-XXXXX`
test -e $PORTFILE && rm -v $PORTFILE

# EMPTYFLAG servers both as empty flag file for remote side,
# and safeguard for background job termination on this side
EMPTYFLAG=$PORTFILE-empty
cp /dev/null $EMPTYFLAG

# this variable has the file name sent over ssh connection
export MY_PORT_FILE=$(basename $PORTFILE)

# background job loop to wait for the temp file to have data
( while [ -f $EMPTYFLAG -a \! -s $PORTFILE ] ; do
     sleep 1 # check once per sec
  done
  sleep 1 # make sure temp file gets the port data

  # first copy temp file, ...
  scp  $PORTFILE $REMOTE:portfiles/$MY_PORT_FILE

  # ...then copy flag file telling temp file contents are up to date
  scp  $EMPTYFLAG $REMOTE:portfiles/$MY_PORT_FILE.flag
) &

# actual ssh terminal connection    
ssh -X -o "SendEnv MY_PORT_FILE" -R0:localhost:631 -R0:localhost:4713 $REMOTE 2> $PORTFILE

# remove files after connection is over
rm -v $PORTFILE $EMPTYFLAG

Kemudian cuplikan untuk sisi jarak jauh, cocok untuk .bashrc :

# only do this if subdir has been created and env variable set
if [ -d ~/portfiles -a "$MY_PORT_FILE" ] ; then

       PORTFILE=~/portfiles/$(basename "$MY_PORT_FILE")
       FLAGFILE=$PORTFILE.flag
       # wait for FLAGFILE to get copied,
       # after which PORTFILE should be complete
       while [ \! -f "$FLAGFILE" ] ; do 
           echo "Waiting for $FLAGFILE..."
           sleep 1
       done

       # use quite exact regexps and head to make this robust
       export CUPS_SERVER=localhost:$(grep '^Allocated port [0-9]\+ .* localhost:631[[:space:]]*$' "$PORTFILE" | head -1 | cut -d" " -f3)
       export PULSE_SERVER=localhost:$(grep '^Allocated port [0-9]\+ .* localhost:4713[[:space:]]*$' "$PORTFILE" | head -1 | cut -d" " -f3)
       echo "Set CUPS_SERVER and PULSE_SERVER"

       # copied files served their purpose, and can be removed right away
       rm -v -- "$PORTFILE" "$FLAGFILE"
fi

Catatan : Kode di atas tentu saja tidak diuji secara menyeluruh dan dapat mengandung semua jenis bug, kesalahan tempel-tempel, dll. Siapa pun yang menggunakannya dengan lebih baik juga memahaminya, gunakan dengan risiko Anda sendiri! Saya mengujinya hanya menggunakan koneksi localhost, dan itu berhasil untuk saya, dalam pengujian saya env. YMMV.

Hyde
sumber
Yang tentu saja mengharuskan saya scpdari sisi jauh ke sisi lokal, yang saya tidak bisa. Saya memiliki pendekatan yang serupa, tetapi saya akan membungkusnya sshsetelah membangun koneksi, kemudian mengirim file itu dari lokal ke remote melalui scpdan kemudian menarik sshklien ke latar depan dan menjalankan skrip di sisi remote. Saya belum menemukan cara untuk skrip latar belakang dan latar depan proses lokal dan jarak jauh dengan baik. Membungkus dan mengintegrasikan sshklien lokal dengan beberapa skrip jarak jauh seperti itu sepertinya bukan pendekatan yang baik.
Bananguin
Ah. Saya pikir Anda harus latar belakang klien sisi scp hanya: (while [ ... ] ; do sleep 1 ; done ; scp ... )&. Kemudian tunggu di latar depan di server .bashrc(dengan asumsi klien mengirim variabel env kanan) untuk file muncul. Saya akan memperbarui jawabannya nanti setelah beberapa pengujian (mungkin tidak ada waktu sampai besok).
hyde
@ Bananguin Versi baru selesai. Tampaknya bekerja untuk saya, jadi harus dapat disesuaikan dengan kasus penggunaan Anda. Tentang "pendekatan yang bagus", ya, tapi saya rasa tidak mungkin ada pendekatan yang bagus di sini. Informasi tersebut perlu diteruskan, dan itu akan selalu berupa peretasan, kecuali jika Anda menambal ssh client dan server untuk melakukannya dengan bersih melalui satu koneksi.
hyde
Dan saya semakin banyak berpikir tentang menambal openssh. Sepertinya bukan masalah besar. Informasi sudah tersedia. Saya hanya perlu mengirimnya ke server. Setiap kali server menerima informasi seperti itu, ia menulisnya ke~/.ssh-${PID}-forwards
Bananguin
1

Cuplikan untuk sisi lokal, cocok untuk .bashrc:

#!/bin/bash

user=$1
host=$2

sshr() {
# 1. connect, get dynamic port, disconnect  
port=`echo "exit" | ssh -R '*:0:127.0.0.1:52698' -t $1 2>&1 | grep 'Allocated port' | awk '/port/ {print $3;}'`
# 2. reconnect with this port and set remote variable
cmds="ssh -R $port:127.0.0.1:52698 -t $1 bash -c \"export RMATE_PORT=$port; bash\""
($cmds)
}

sshr $user@$host
ToxeH
sumber
0

Saya telah mencapai hal yang sama dengan membuat pipa pada klien lokal, kemudian mengarahkan stderr ke pipa yang juga diarahkan ke input ssh. Tidak diperlukan banyak koneksi ssh untuk menganggap porta yang dikenal bebas bisa gagal. Dengan cara ini spanduk masuk dan teks "Alokasi port ### ..." dialihkan ke host jarak jauh.

Saya memiliki skrip sederhana pada host getsshport.shyang dijalankan pada host jarak jauh yang membaca input diarahkan dan mem-parsing port. Selama skrip ini tidak berakhir, ssh remote forward tetap terbuka.

sisi lokal

mkfifo pipe
ssh -R "*:0:localhost:22" user@remotehost "~/getsshport.sh" 3>&1 1>&2 2>&3 < pipe | cat > pipe

3>&1 1>&2 2>&3 adalah sedikit trik untuk menukar stderr dan stdout, sehingga stderr disalurkan ke cat, dan semua output normal dari ssh ditampilkan pada stderr.

sisi jarak jauh ~ / getsshport.sh

#!/bin/sh
echo "Connection from $SSH_CLIENT"
while read line
do
    echo "$line" # echos everything sent back to the client
    echo "$line" | sed -n "s/Allocated port \([0-9]*\) for remote forward to \(.*\)\:\([0-9]*\).*/client port \3 is on local port \1/p" >> /tmp/allocatedports
done

Saya memang mencoba greppesan "dialokasikan port" di sisi lokal terlebih dahulu sebelum mengirimnya melalui ssh, tetapi tampaknya ssh akan memblokir menunggu pipa untuk terbuka di stdin. grep tidak membuka pipa untuk menulis sampai menerima sesuatu, jadi ini pada dasarnya deadlock. catNamun tampaknya tidak memiliki perilaku yang sama, dan membuka pipa untuk menulis segera memungkinkan ssh untuk membuka koneksi.

ini adalah masalah yang sama di sisi remote, dan mengapa readbaris demi baris bukan hanya grep dari stdin - jika tidak `/ tmp / dialokasikanports 'tidak ditulis sampai terowongan ssh ditutup yang mengalahkan seluruh tujuan

Memipipkan stderr ssh ke perintah seperti ~/getsshport.shlebih disukai, karena tanpa menentukan perintah, teks spanduk, atau apa pun yang ada di dalam pipa dieksekusi pada shell jauh.

JesseMcL
sumber
bagus. Saya menambahkan renice +10 $$; exec catsebelum doneuntuk menghemat sumber daya.
Spongman
0

Ini rumit, penanganan sisi server tambahan sepanjang SSH_CONNECTIONatau DISPLAYakan bagus, tetapi tidak mudah untuk ditambahkan: bagian dari masalahnya adalah bahwa hanya sshklien yang tahu tujuan lokal, paket permintaan (ke server) berisi hanya alamat dan port jarak jauh.

Jawaban lain di sini memiliki berbagai solusi tidak wajar untuk menangkap sisi klien ini dan mengirimkannya ke server. Inilah pendekatan alternatif yang tidak terlalu cantik untuk jujur, tapi setidaknya pesta jelek ini disimpan di sisi klien ;-)

  • sisi klien, tambahkan / ubah SendEnvsehingga kami dapat mengirim beberapa variabel lingkungan secara native di atas ssh (mungkin tidak default)
  • sisi server, tambahkan / ubah AcceptEnvuntuk menerima yang sama (mungkin tidak diaktifkan secara default)
  • pantau sshoutput stderr klien dengan pustaka yang dimuat secara dinamis, dan perbarui lingkungan klien ssh selama pengaturan
  • mengambil sisi server variabel lingkungan di skrip profil / login

Ini berfungsi (dengan senang hati, untuk sekarang) karena remote forward diatur dan dicatat sebelum lingkungan dipertukarkan (konfirmasi dengan ssh -vv ...). Pustaka yang dimuat secara dinamis harus menangkap write()fungsi libc ( ssh_confirm_remote_forward()logit()do_log()write()). Mengarahkan atau membungkus fungsi dalam biner ELF (tanpa kompilasi ulang) adalah urutan besarnya lebih kompleks daripada melakukan hal yang sama untuk suatu fungsi di perpustakaan dinamis.

Di klien .ssh/config(atau baris perintah -o SendEnv ...)

Host somehost
  user whatever
  SendEnv SSH_RFWD_*

Di server sshd_config(diperlukan root / perubahan administrasi)

AcceptEnv LC_* SSH_RFWD_*

Pendekatan ini bekerja untuk klien Linux dan tidak memerlukan apa-apa khusus pada server, itu harus bekerja untuk * nix lain dengan beberapa perubahan kecil. Bekerja dari setidaknya OpenSSH 5.8p1 hingga 7.5p1.

Kompilasi dengan gcc -Wall -shared -ldl -Wl,-soname,rfwd -o rfwd.so rfwd.c Invoke dengan:

LD_PRELOAD=./rfwd.so ssh -R0:127.0.0.1:4713 -R0:localhost:631 somehost

Kode:

#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
#include <string.h>
#include <stdlib.h>

// gcc -Wall -shared  -ldl -Wl,-soname,rfwd -o rfwd.so rfwd.c

#define DEBUG 0
#define dfprintf(fmt, ...) \
    do { if (DEBUG) fprintf(stderr, "[%14s#%04d:%8s()] " fmt, \
          __FILE__, __LINE__, __func__,##__VA_ARGS__); } while (0)

typedef ssize_t write_fp(int fd, const void *buf, size_t count);
static write_fp *real_write;

void myinit(void) __attribute__((constructor));
void myinit(void)
{
    void *dl;
    dfprintf("It's alive!\n");
    if ((dl=dlopen(NULL,RTLD_NOW))) {
        real_write=dlsym(RTLD_NEXT,"write");
        if (!real_write) dfprintf("error: %s\n",dlerror());
        dfprintf("found %p write()\n", (void *)real_write);
    } else {
        dfprintf(stderr,"dlopen() failed\n");
    }
}

ssize_t write(int fd, const void *buf, size_t count)
{
     static int nenv=0;

     // debug1: Remote connections from 192.168.0.1:0 forwarded to local address 127.0.0.1:1000
     //  Allocated port 44284 for remote forward to 127.0.0.1:1000
     // debug1: All remote forwarding requests processed
     if ( (fd==2) && (!strncmp(buf,"Allocated port ",15)) ) {
         char envbuf1[256],envbuf2[256];
         unsigned int rport;
         char lspec[256];
         int rc;

         rc=sscanf(buf,"Allocated port %u for remote forward to %256s",
          &rport,lspec);

         if ( (rc==2) && (nenv<32) ) {
             snprintf(envbuf1,sizeof(envbuf1),"SSH_RFWD_%i",nenv++);
             snprintf(envbuf2,sizeof(envbuf2),"%u %s",rport,lspec);
             setenv(envbuf1,envbuf2,1);
             dfprintf("setenv(%s,%s,1)\n",envbuf1,envbuf2);
         }
     }
     return real_write(fd,buf,count);
}

(Ada beberapa jebakan beruang glibc terkait dengan versi simbol dengan pendekatan ini, tetapi write()tidak memiliki masalah ini.)

Jika Anda merasa berani, Anda bisa mengambil setenv()kode terkait dan menambalnya ke ssh.c ssh_confirm_remote_forward()fungsi callback.

Ini menetapkan variabel lingkungan bernama SSH_RFWD_nnn, periksa ini di profil Anda, misalnya dibash

for fwd in ${!SSH_RFWD_*}; do
    IFS=" :" read lport rip rport <<< ${!fwd}
    [[ $rport -eq "631" ]] && export CUPS_SERVER=localhost:$lport
    # ...
done

Peringatan:

  • tidak ada banyak kesalahan saat memeriksa kode
  • mengubah lingkungan dapat menyebabkan masalah terkait thread, PAM menggunakan thread, saya tidak mengharapkan masalah tapi saya belum mengujinya
  • sshsaat ini tidak dengan jelas mencatat penerusan penuh bentuk * local: port: remote: port * (jika diperlukan penguraian lebih lanjut dari debug1pesan ssh -vakan diperlukan), tetapi Anda tidak memerlukan ini untuk kasus penggunaan Anda

Anehnya, OpenSSH tampaknya tidak memiliki sarana untuk mengambil informasi tentang penerusan porta.

Anda dapat (sebagian) melakukan ini secara interaktif dengan melarikan diri ~#, anehnya implementasi melompati saluran yang mendengarkan, itu hanya daftar yang terbuka (yaitu TCP ESTABLISHED), dan itu tidak mencetak bidang yang berguna dalam hal apa pun. Lihatchannels.c channel_open_message()

Anda dapat menambal yang berfungsi untuk mencetak rincian untuk SSH_CHANNEL_PORT_LISTENERslot, tapi itu hanya membuat Anda yang forwardings lokal ( saluran tidak sama dengan yang sebenarnya depan ). Atau, Anda bisa menambalnya untuk membuang dua tabel penerusan dari optionsstruct global :

#include "readconf.h"
Options options;  /* extern */
[...]
snprintf(buf, sizeof buf, "Local forwards:\r\n");
buffer_append(&buffer, buf, strlen(buf));
for (i = 0; i < options.num_local_forwards; i++) {
     snprintf(buf, sizeof buf, "  #%d listen %s:%d connect %s:%d\r\n",i,
       options.local_forwards[i].listen_host,
       options.local_forwards[i].listen_port,
       options.local_forwards[i].connect_host,
       options.local_forwards[i].connect_port);
     buffer_append(&buffer, buf, strlen(buf));
}
snprintf(buf, sizeof buf, "Remote forwards:\r\n");
buffer_append(&buffer, buf, strlen(buf));
for (i = 0; i < options.num_remote_forwards; i++) {
     snprintf(buf, sizeof buf, "  #%d listen %s:%d connect %s:%d\r\n",i,
       options.remote_forwards[i].listen_host,
       options.remote_forwards[i].listen_port,
       options.remote_forwards[i].connect_host,
       options.remote_forwards[i].connect_port);
     buffer_append(&buffer, buf, strlen(buf));
}

Ini berfungsi dengan baik, meskipun itu bukan solusi "terprogram", dengan peringatan bahwa kode klien tidak (belum ditandai oleh XXX di sumbernya) memperbarui daftar ketika Anda menambahkan / menghapus penerusan on-the-fly ( ~C)


Jika server adalah Linux Anda memiliki satu opsi lagi, ini adalah yang saya gunakan secara umum, meskipun untuk penerusan lokal daripada remote. loadalah 127.0.0.1/8, di Linux Anda dapat secara transparan mengikat ke alamat mana pun di 127/8 , sehingga Anda dapat menggunakan port tetap jika Anda menggunakan alamat 127.xyz yang unik, misalnya:

mr@local:~$ ssh -R127.53.50.55:44284:127.0.0.1:44284 remote
[...]
mr@remote:~$ ss -atnp src 127.53.50.55
State      Recv-Q Send-Q        Local Address:Port          Peer Address:Port 
LISTEN     0      128            127.53.50.55:44284                    *:*    

Ini tunduk pada pengikatan port dengan hak istimewa <1024, OpenSSH tidak mendukung kemampuan Linux dan memiliki pemeriksaan UID hard-kode pada sebagian besar platform.

Oktet yang dipilih dengan bijak (mnemonik ordinal ASCII dalam kasus saya) membantu mengurai kekacauan di akhir hari.

mr.spuratic
sumber