Ищу тему рыбы с powerline, полным путем и возвратом и возвратом каретки после строки приглашения

Это сложный вопрос, дополнительная обработка на стороне сервера, например SSH_CONNECTION или DISPLAY, была бы отличной, но добавить ее нелегко. : часть проблемы в том, что только ssh клиент знает локальный пункт назначения, пакет запроса (к серверу) содержит только удаленный адрес и порт.

В других ответах здесь есть различные некрасивые решения для захвата этой клиентской стороны и отправки ее на сервер. Вот альтернативный подход, который не очень красив, если честно, но, по крайней мере, эта уродливая партия сохраняется на стороне клиента ;-)

  • на стороне клиента, добавьте/измените SendEnv, чтобы мы могли отправить некоторые переменные окружения изначально используются через ssh (вероятно, не по умолчанию)
  • на стороне сервера, добавьте/измените AcceptEnv, чтобы они принимали такие же (вероятно, не включены по умолчанию)
  • отслеживайте клиент ssh вывод stderr с динамически загружаемой библиотекой и обновление клиентской среды ssh во время установки соединения
  • получение переменных среды на стороне сервера в сценарии профиля/входа

Это работает (к счастью, на данный момент в любом случае) поскольку удаленные переадресации устанавливаются и записываются до обмена средой (подтвердите с помощью ssh -vv ... ).Динамически загружаемая библиотека должна захватить функцию write() libc (ssh_confirm_remote_forward()logit()do_log()написать()). Перенаправление или перенос функций в двоичный файл ELF (без перекомпиляции) на порядки сложнее, чем то же самое для функции в динамической библиотеке.

На клиенте .ssh/config (или в командной строке -o SendEnv ... )

Host somehost
  user whatever
  SendEnv SSH_RFWD_*

На сервере sshd_config (root/administrative требуется изменение)

AcceptEnv LC_* SSH_RFWD_*

Этот подход работает для клиентов Linux и не требует ничего особенного на сервере, он должен работать и для других *nix с некоторыми небольшими изменениями. Работает как минимум с OpenSSH 5.8p1 до 7.5p1.

Компилировать с помощью gcc -Wall -shared -ldl -Wl,-soname,rfwd -o rfwd.so rfwd.c Вызов с помощью:

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

Код:

#define _GNU_SOURCE
#include 
#include 
#include 
#include 

// 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);
}

(Существуют некоторые ловушки glibc, связанные с управлением версиями символов при таком подходе, но write() не имеет этой проблемы.)

Если вы Если вы чувствуете себя смелым, вы можете взять код, связанный с setenv(), и вставить его в функцию обратного вызова ssh.c ssh_confirm_remote_forward().

Это устанавливает переменные среды с именем SSH_RFWD_nnn, проверьте их в своем профиле, например.в bash

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

Предостережения:

  • в коде не так много проверок ошибок
  • изменение среды может вызвать проблемы, связанные с потоками, PAM использует потоки, я не ожидаю проблем но я не проверял, что
  • ssh в настоящее время явно не регистрирует полную пересылку формы * local:port:remote:port* (при необходимости дальнейшего анализа сообщений debug1 с ssh -v), но вам это не нужно для вашего варианта использования.

Достаточно странно, что OpenSSH не имеет средств для получения информации о переадресации портов.

Вы можете (частично) сделать это в интерактивном режиме с помощью escape ~#, как ни странно, реализация пропускает прослушиваемые каналы, она перечисляет только открытые (т.е. TCP ESTABLISHED) и не печатает полезные поля в любом случае. См. channels.c channel_open_message()

Вы можете исправить эту функцию, чтобы распечатать детали для слотов SSH_CHANNEL_PORT_LISTENER, но это даст вам только локальную переадресацию (каналы не то же самое, что фактические форварды). Или вы можете исправить его, чтобы выгрузить две таблицы переадресации из глобальной структуры options:

#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));
}

Это работает нормально, хотя это и не "программное" решение, с оговоркой, что клиентский код этого не делает ( тем не менее, в исходном коде он помечен как XXX) обновите список, когда вы добавляете/удаляете переадресацию на лету (~C)


Если сервер(ы) Linux, у вас есть еще один вариант, это тот, который я обычно использую, хотя для локальной переадресации, а не для удаленной.lo — это 127.0.0.1/8, в Linux вы можете прозрачно привязываться к любому адресу в 127/8, поэтому вы можете использовать фиксированные порты, если используете уникальные адреса 127.xyz, например :

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                    *:*    

Это зависит от привязки привилегированных портов

Грамотно подобранные октеты (в моем случае порядковые мнемоники ASCII) помогают распутать клубок в конце дня.

1
09.02.2017, 02:30
1 ответ

Похоже, вы говорите о теме "бира" oh-my-zsh. Вы можете проверить это здесь.

Это также может быть развлечь.

0
28.01.2020, 01:01

Теги

Похожие вопросы