Задать вопрос
  • Как js может управлять службой на хосте?

    @Quqas Автор вопроса
    вот как это
    $response = nfqwsServiceAction($_POST['cmd']);
    интерпретировать?
    Написано
  • Как js может управлять службой на хосте?

    @Quqas Автор вопроса
    нашёл таки php но не в браузере а как файл

    php

    <?php
    
    ini_set('memory_limit', '32M');
    
    define('ROOT_DIR', file_exists('/opt/etc/nfqws/nfqws.conf') ? '/opt' : '');
    define('SCRIPT_NAME', ROOT_DIR ? 'S51nfqws' : 'nfqws-keenetic');
    
    function normalizeString(string $s): string {
        // Convert all line-endings to UNIX format.
        $s = str_replace(array("\r\n", "\r", "\n"), "\n", $s);
    
        // Don't allow out-of-control blank lines.
        $s = preg_replace("/\n{3,}/", "\n\n", $s);
    
        $lastChar = substr($s, -1);
        if ($lastChar !== "\n" && !empty($s)) {
            $s .= "\n";
        }
    
        return $s;
    }
    
    function getFiles($path = ROOT_DIR . '/etc/nfqws'): array {
        // GLOB_BRACE is unsupported in openwrt
        $files = array_filter(glob($path . '/*'), function ($file) {
            return is_file($file) && preg_match('/\.(list|list-opkg|list-old|conf|conf-opkg|conf-old|apk-new)$/i', $file);
        });
        $logfile = ROOT_DIR . '/var/log/nfqws.log';
        $basenames = array_map(fn($file) => basename($file), $files);
        if (file_exists($logfile)) {
            array_push($basenames, basename($logfile));
        }
    
        $priority = ['nfqws.conf' => -5, 'user.list' => -4, 'exclude.list' => -3, 'auto.list' => -2, 'nfqws.log' => -1];
        usort($basenames, fn($a, $b) => ($priority[$a] ?? 1) - ($priority[$b] ?? -1));
    
        return $basenames;
    }
    
    function getFileContent(string $filename, $path = ROOT_DIR . '/etc/nfqws'): string {
        return file_get_contents($path . '/' . basename($filename));
    }
    
    function getLogContent(string $filename, $path = ROOT_DIR . '/var/log'): string {
        $file = file($path . '/' . basename($filename));
        $file = array_reverse($file);
        return implode("", $file);
    }
    
    function saveFile(string $filename, string $content, $path = ROOT_DIR . '/etc/nfqws') {
        $filename = basename($filename);
        $file = $path . '/' . $filename;
        return file_exists($file) && file_put_contents($file, normalizeString($content)) !== false;
    }
    
    function saveLog(string $filename, string $content, $path = ROOT_DIR . '/var/log') {
        return saveFile($filename, $content, $path);
    }
    
    function removeFile(string $filename, $path = ROOT_DIR . '/etc/nfqws') {
        $filename = basename($filename);
        $file = $path . '/' . $filename;
        if (file_exists($file)) {
            return unlink($file);
        } else {
            return false;
        }
    }
    
    function nfqwsServiceStatus() {
        $output = null;
        exec(ROOT_DIR . "/etc/init.d/" . SCRIPT_NAME . " status", $output);
        return str_contains($output[0] ?? '', 'is running');
    }
    
    function nfqwsServiceAction(string $action) {
        $output = null;
        $retval = null;
        exec(ROOT_DIR . "/etc/init.d/" . SCRIPT_NAME . " $action", $output, $retval);
        return array('output' => $output, 'status' => $retval);
    }
    
    function opkgUpgradeAction() {
        $output = null;
        $retval = null;
        exec("opkg update && opkg upgrade nfqws-keenetic nfqws-keenetic-web", $output, $retval);
        if (empty($output)) {
            $output[] = 'Nothing to update';
        }
        return array('output' => $output, 'status' => $retval);
    }
    
    function apkUpgradeAction() {
        $output = null;
        $retval = null;
        exec("apk --update-cache add nfqws-keenetic nfqws-keenetic-web", $output, $retval);
        if (empty($output)) {
            $output[] = 'Nothing to update';
        }
        return array('output' => $output, 'status' => $retval);
    }
    
    function upgradeAction() {
        return file_exists('/usr/bin/apk') ? apkUpgradeAction() : opkgUpgradeAction();
    }
    
    function authenticate($username, $password) {
        $passwdFile = ROOT_DIR . '/etc/passwd';
        $shadowFile = ROOT_DIR . '/etc/shadow';
    
        $users = file(file_exists($shadowFile) ? $shadowFile : $passwdFile);
        $user = preg_grep("/^$username/", $users);
    
        if ($user) {
            list(, $passwdInDB) = explode(':', array_pop($user));
            if (empty($passwdInDB)) {
                return empty($password);
            }
            if (crypt($password, $passwdInDB) == $passwdInDB) {
                return true;
            }
        }
    
        return false;
    }
    
    function main() {
        if (!isset($_SERVER['REQUEST_METHOD']) || $_SERVER['REQUEST_METHOD'] !== 'POST') {
            http_response_code(302);
            header('Location: index.html');
            exit();
        }
    
        session_start();
        if (!isset($_SESSION['auth']) || !$_SESSION['auth']) {
            if ($_POST['cmd'] !== 'login' || !isset($_POST['user']) || !isset($_POST['password']) || !authenticate($_POST['user'], $_POST['password'])) {
                http_response_code(401);
                exit();
            } else {
                $_SESSION['auth'] = true;
            }
        }
    
        switch ($_POST['cmd']) {
            case 'filenames':
                $files = getFiles();
                $response = array('status' => 0, 'files' => $files, 'service' => nfqwsServiceStatus());
                break;
    
            case 'filecontent':
                if (str_ends_with($_POST['filename'], '.log')) {
                    $content = getLogContent($_POST['filename']);
                } else {
                    $content = getFileContent($_POST['filename']);
                }
                $response = array('status' => 0, 'content' => $content, 'filename' => $_POST['filename']);
                break;
    
            case 'filesave':
                if (str_ends_with($_POST['filename'], '.log')) {
                    $result = saveLog($_POST['filename'], $_POST['content']);
                } else {
                    $result = saveFile($_POST['filename'], $_POST['content']);
                }
                $response = array('status' => $result ? 0 : 1, 'filename' => $_POST['filename']);
                break;
    
            case 'fileremove':
                $result = removeFile($_POST['filename']);
                $response = array('status' => $result ? 0 : 1, 'filename' => $_POST['filename']);
                break;
    
            case 'reload':
            case 'restart':
            case 'stop':
            case 'start':
                $response = nfqwsServiceAction($_POST['cmd']);
                break;
    
            case 'upgrade':
                $response = upgradeAction();
                break;
    
            case 'login':
                $response = array('status' => 0);
                break;
    
            case 'logout':
                $_SESSION['auth'] = false;
                $response = array('status' => 0);
                break;
    
            default:
                http_response_code(405);
                exit();
        }
    
        header('Content-Type: application/json; charset=utf-8');
        http_response_code(200);
        echo json_encode($response);
        exit();
    }
    
    main();

    Написано
  • Как js может управлять службой на хосте?

    @Quqas Автор вопроса
    и ещё скриптик короткий
    const TLN={eventList:{},update_line_numbers:function(e,t){let n=e.value.split("\n").length-t.children.length;if(n>0){const e=document.createDocumentFragment();for(;n>0;){const t=document.createElement("span");t.className="tln-line",e.appendChild(t),n--}t.appendChild(e)}for(;n<0;)t.removeChild(t.lastChild),n++},append_line_numbers:function(e){const t=document.getElementById(e);if(null==t)return console.warn("[tln.js] Couldn't find textarea of id '"+e+"'");if(-1!=t.className.indexOf("tln-active"))return console.warn("[tln.js] textarea of id '"+e+"' is already numbered");t.classList.add("tln-active"),t.style={};const n=document.createElement("div");n.className="tln-wrapper",t.parentNode.insertBefore(n,t),TLN.update_line_numbers(t,n),TLN.eventList[e]=[];const l=["propertychange","input","keydown","keyup"],o=function(e,t){return function(n){(10!=+e.scrollLeft||37!=n.keyCode&&37!=n.which&&"ArrowLeft"!=n.code&&"ArrowLeft"!=n.key)&&36!=n.keyCode&&36!=n.which&&"Home"!=n.code&&"Home"!=n.key&&13!=n.keyCode&&13!=n.which&&"Enter"!=n.code&&"Enter"!=n.key&&"NumpadEnter"!=n.code||(e.scrollLeft=0),TLN.update_line_numbers(e,t)}}(t,n);for(let n=l.length-1;n>=0;n--)t.addEventListener(l[n],o),TLN.eventList[e].push({evt:l[n],hdlr:o});const r=["change","mousewheel","scroll"],s=function(e,t){return function(){t.scrollTop=e.scrollTop}}(t,n);for(let n=r.length-1;n>=0;n--)t.addEventListener(r[n],s),TLN.eventList[e].push({evt:r[n],hdlr:s})},remove_line_numbers:function(e){const t=document.getElementById(e);if(null==t)return console.warn("[tln.js] Couldn't find textarea of id '"+e+"'");if(-1==t.className.indexOf("tln-active"))return console.warn("[tln.js] textarea of id '"+e+"' isn't numbered");t.classList.remove("tln-active");const n=t.previousSibling;if("tln-wrapper"==n.className&&n.remove(),TLN.eventList[e]){for(let n=TLN.eventList[e].length-1;n>=0;n--){const l=TLN.eventList[e][n];t.removeEventListener(l.evt,l.hdlr)}delete TLN.eventList[e]}}};
    Написано
  • Как js может управлять службой на хосте?

    @Quqas Автор вопроса
    php якобы нету
    тока html(f12+sources)
    index

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>nfqws-keenetic</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
        <link rel="shortcut icon" type="image/x-icon" href="favicon.ico">
        <link rel="apple-touch-icon" href="icon.png">
        <link rel="icon" href="icon.png" sizes="192x192">
        <link rel="manifest" href="manifest.json">
        <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
        <meta http-equiv="Pragma" content="no-cache" />
        <meta http-equiv="Expires" content="0" />
    
        <meta name="MobileOptimized" content="320">
        <meta name="HandheldFriendly" content="true">
        <meta name="theme-color" media="(prefers-color-scheme: light)" content="#fff">
        <meta name="theme-color" media="(prefers-color-scheme: dark)" content="#1b2434">
        <meta name="color-scheme" content="light dark">
    
        <script defer src="tln.min.js?v=v2.8.4"></script>
        <script defer src="script.js?v=v2.8.4" type="module"></script>
    
        <link rel="stylesheet" href="tln.min.css?v=v2.8.4">
        <link rel="stylesheet" href="style.css?v=v2.8.4">
    </head>
    <body class="disabled unknown">
    <script>
        const theme = localStorage.getItem('theme');
        if (theme) {
            const root = document.querySelector(':root');
            root.dataset.theme = theme;
        }
    </script>
    
    <header>
        <h1 class="logo">nfqws-keenetic <span id="status"></span></h1>
        <button class="button red" id="save">Save</button>
        <button class="button" id="restart">Restart</button>
        <button class="button" id="dropdown"></button>
        <ul id="dropdown-menu" class="hidden">
            <li class="dropdown-item" id="reload">Reload</li>
            <li class="dropdown-item" id="stop">Stop</li>
            <li class="dropdown-item" id="start">Start</li>
            <li class="dropdown-item" id="upgrade">Update</li>
        </ul>
    </header>
    
    <nav></nav>
    
    <article>
        <div class="textarea-container">
            <textarea id="config" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autofocus></textarea>
        </div>
    </article>
    
    <footer>
        <a class="footer-tab" href="https://github.com/Anonym-tsk/nfqws-keenetic/" target="_blank">GitHub</a>
        <a class="footer-tab" href="https://anonym-tsk.github.io/nfqws-keenetic/" target="_blank">Repository</a>
        <span id="theme" class="footer-tab" title="Change theme"></span>
        <span id="logout" class="footer-tab" title="Logout"></span>
        <span id="version">v2.8.4</span>
    </footer>
    
    <div id="overlay"></div>
    
    <div id="alert" class="popup hidden">
        <pre class="popup-content"></pre>
        <div class="popup-footer">
            <button class="popup-yes">Yes</button>
            <button class="popup-no">No</button>
            <button class="popup-close">Close</button>
        </div>
    </div>
    
    <div id="login-form" class="popup hidden">
        <div class="popup-content">
            <input type="text" class="login-input" id="login" autocomplete="false" autofocus placeholder="Login" />
            <input type="password" class="login-input" id="password" placeholder="Password" />
        </div>
        <div class="popup-footer">
            <button class="popup-yes">Login</button>
        </div>
    </div>
    
    </body>
    </html>

    Написано
  • Как js может управлять службой на хосте?

    @Quqas Автор вопроса
    начало скрипта

    class UI {
        constructor() {
            TLN.append_line_numbers('config');
    
            this.$tabs = document.querySelector('nav');
    
            this.buttons = this._initButtons();
            this.tabs = this._initTabs();
            this.textarea = this._initTextarea();
            this.version = this._initVersion();
            this.popup = this._initPopups();
            this.login = this._initLoginForm();
        }
    
        _initTabs() {
            const tabs = {};
            let currentFile = '';
    
            const add = (filename) => {
                const tab = document.createElement('div');
                tab.classList.add('nav-tab');
                tab.textContent = filename;
    
                const isConf = filename.endsWith('.conf');
                const isList = filename.endsWith('.list');
                const isLog = filename.endsWith('.log');
    
                if (isLog) {
                    const clear = document.createElement('div');
                    clear.classList.add('nav-clear');
                    clear.setAttribute('title', 'Clear log');
    
                    clear.addEventListener('click', async (e) => {
                        e.preventDefault();
                        e.stopPropagation();
    
                        const yesno = await this.popup.confirm('Clear log?');
                        if (!yesno) {
                            return;
                        }
    
                        const result = await saveFile(filename, '');
                        if (!result.status) {
                            if (filename === currentFile) {
                                this.textarea.value = '';
                            }
                        } else {
                            this.popup.alert(`clear ${filename}`, `Error: ${result.status}`);
                        }
                    });
    
                    tab.appendChild(clear);
                } else if (!isConf && !isList) {
                    tab.classList.add('secondary');
                    const trash = document.createElement('div');
                    trash.classList.add('nav-trash');
                    trash.setAttribute('title', 'Delete file');
    
                    trash.addEventListener('click', async (e) => {
                        e.preventDefault();
                        e.stopPropagation();
    
                        const yesno = await this.popup.confirm('Delete file?');
                        if (!yesno) {
                            return;
                        }
    
                        const result = await removeFile(filename);
                        if (!result.status) {
                            remove(filename);
                        } else {
                            this.popup.alert(`remove ${filename}`, `Error: ${result.status}`);
                        }
                    });
    
                    tab.appendChild(trash);
                }
    
                tab.addEventListener('click', async () => this.loadFile(filename));
    
                this.$tabs.appendChild(tab);
                tabs[filename] = tab;
            };
    
            const remove = (filename) => {
                for (const [key, tab] of Object.entries(tabs)) {
                    if (key === filename) {
                        tab.parentNode.removeChild(tab);
                        delete tabs[key];
    
                        if (filename === currentFile) {
                            this.textarea.save();
                            activateFirst();
                        }
                        break;
                    }
                }
            };
    
            const activate = (filename) => {
                for (const [key, tab] of Object.entries(tabs)) {
                    tab.classList.toggle('active', filename === key);
                    if (filename === key) {
                        currentFile = filename;
                    }
                }
            };
    
            const activateFirst = () => {
                Object.values(tabs)[0].click();
            };
    
            return {
                add,
                remove,
                activate,
                activateFirst,
                get currentFileName() {
                    return currentFile;
                }
            };
        }
    
        _initTextarea() {
            const element = document.getElementById('config');
            let originalText = element.value;
            let textChanged = false;
    
            const save = () => {
                originalText = element.value;
                textChanged = false;
                this.setChanged(false);
            };
    
            element.addEventListener('input', _debounce(() => {
                textChanged = element.value !== originalText;
                this.setChanged(textChanged);
            }, 300));
    
            element.addEventListener('keydown', (e) => {
                if ((e.ctrlKey || e.metaKey) && e.key === 's') {
                    e.preventDefault();
                    this.buttons.click();
                }
            });
    
            return {
                get value() {
                    return element.value;
                },
                set value(text) {
                    element.value = text;
                    save();
                    // Update line numbers
                    const event = new Event('input');
                    element.dispatchEvent(event);
                },
                get changed() {
                    return textChanged;
                },
                save,
                disabled(status) {
                    if (status) {
                        element.setAttribute('disabled', 'disabled');
                    } else {
                        element.removeAttribute('disabled');
                    }
                },
                readonly(status) {
                    if (status) {
                        element.setAttribute('readonly', 'readonly');
                    } else {
                        element.removeAttribute('readonly');
                    }
                },
            };
        }
    
        _initVersion() {
            const element = document.getElementById('version');
            const match = element.textContent.match(/^v([0-9]+)\.([0-9]+)\.([0-9]+)$/);
    
            const value = () => {
                return match ? [match[1], match[2], match[3]] : null;
            };
    
            const checkUpdate = async () => {
                if (!value()) {
                    return;
                }
    
                const latest = await getLatestVersion();
                if (!latest) {
                    return;
                }
    
                const updateAvailable = compareVersions(value(), latest);
                if (updateAvailable) {
                    const link = document.createElement('a');
                    const tag = `v${latest[0]}.${latest[1]}.${latest[2]}`;
                    link.textContent = `(${tag})`;
                    link.href = `https://github.com/Anonym-tsk/nfqws-keenetic/releases/tag/${tag}`;
                    link.target = '_blank';
                    element.appendChild(link);
                }
            };
    
            return {
                get value() {
                    return value();
                },
                checkUpdate,
            }
        }
    
        _initPopups() {
            const element = document.getElementById('alert');
            const alertContent = element.querySelector('.popup-content');
            const buttonClose = element.querySelector('.popup-close');
            const buttonYes = element.querySelector('.popup-yes');
            const buttonNo = element.querySelector('.popup-no');
    
            const alert = (...text) => {
                this.disableUI();
                alertContent.textContent = `> ${text.join("\n")}`;
                element.classList.add('alert');
                element.classList.remove('hidden', 'confirm', 'locked');
            };
    
            const hide = () => {
                element.classList.add('hidden');
                element.classList.remove('locked');
                this.enableUI();
            }
    
            const confirm = async (text) => {
                this.disableUI();
                alertContent.textContent = text;
                element.classList.add('confirm');
                element.classList.remove('hidden', 'alert', 'locked');
    
                return new Promise((resolve) => {
                    buttonYes.addEventListener('click', function ok() {
                        buttonYes.removeEventListener('click', ok);
                        resolve(true);
                    });
                    buttonNo.addEventListener('click', function fail() {
                        buttonNo.removeEventListener('click', fail);
                        resolve(false);
                    });
                });
            };
    
            const process = async (text, fn, ...args) => {
                this.disableUI();
                alertContent.textContent = `> ${text}\n`;
                element.classList.add('alert', 'locked');
                element.classList.remove('hidden', 'confirm');
                let status = true;
    
                const result = await fn(...args);
                if (!result.status) {
                    alertContent.textContent += Array.from(result.output).join("\n");
                } else {
                    alertContent.textContent += `Error: ${result.status}`;
                    status = false;
                }
                element.classList.remove('locked');
    
                return new Promise((resolve) => {
                    buttonClose.addEventListener('click', function close() {
                        buttonYes.removeEventListener('click', close);
                        resolve(status);
                    });
                });
            };
    Написано
  • Как отдебажить почему openssl s_client не устанавливает туннель?

    @Quqas Автор вопроса
    AUser0,
    Хотите - в HTTP-запросе представляйтесь веб браузером, не хотите - не представляйтесь...

    ну так именно этот момент и неясен. как это варьировать?
    в s_client кроме [-connect host:port] [-servername name]
    другие параметры не использовал и ихнее влияние неясно
    [-connect host:port] в случае извне
    могу два варианта. как домен 3го или 4го уровня - порт полюбасу 443 -- попадает извне на прокси
    а [-servername name] задаёт sni строго 4го уровня. именно по этому sni прокси переправлять и должен на внутренний ip\порт s_server. и с браузером работает (см.выше)

    но получается принудительно расшифровывается по пути?
    Написано
  • Как отдебажить почему openssl s_client не устанавливает туннель?

    @Quqas Автор вопроса
    AUser0, ну так а что именно не так? какбы вы написали труЪ команду для s_client ?
    и как быть с тем что посередине между client и server стоит https reverse proxy?
    браузер тоже например не тот серт использует при подключении извне(но до server таки долазит и кажет именно его страницу, но серт в свойствах от прокси). а изнутри таки серт от openssl s_server
    Написано
  • Как отдебажить почему openssl s_client не устанавливает туннель?

    @Quqas Автор вопроса
    ValdikSS,
    самого web-интерфейса роутера

    это-то вполне.
    любой внутренний и даже не очень ip(типа момеда который какбы "вовне" по отношению к роутеру)
    не пропустит не-web-трафик

    а вот это да. но начиналось то всё (в гугле) что ssh в этот самый web можно завернуть. но оказывается нельзя или нетольколишьвсе варианты tls заворачиваются
    но как-то труЪ https браузеров идёт, а остальное уже не очень. хотя обещали(в гугле) с три короба
    Написано
  • Как отдебажить почему openssl s_client не устанавливает туннель?

    @Quqas Автор вопроса
    ответить то ответили - но я не могу поставить рекомендованные "усложнения" nginx

    а s_client такое впечатление не может сквозь nginx прокси пролезть - и "руки-жмёт" с ним а не s_server (который тоже вовнутри сети)

    осталось только в этом на 146% убедится

    или совет как заставить таки "пробится" вовнутрь
    и тогда уже вовнутре ssl пойдёт ssh (но это да уже обсудили)
    Написано
  • Как отдебажить почему openssl s_client не устанавливает туннель?

    @Quqas Автор вопроса
    в случае браузера серт не сервака, а прокси становится (в самом браузере) но показывает именно страницу сервера
    может и s_client на первом попавшемся tls пытается соединится?
    хотя мысль что должен проходить через прокси внутрь до сервака.
    Написано
  • Как отдебажить почему openssl s_client не устанавливает туннель?

    @Quqas Автор вопроса
    AUser0, даже излишне много
    а понимания дошло до сервера или нет - не добавляет
    что именно в выводе надо искать?
    Написано
  • SSH +reverse https proxy, при чём тут openSSL(VPN)?

    @Quqas Автор вопроса
    но где такое в
    location / {
    proxy_pass http://127.0.0.1:22;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    }
    ?
    за вычетом того что у меня не localhost а другой ip
    https://dev.to/udara_dananjaya/how-to-access-ssh-o...
    тут некий стрим правда
    https://iyzico.engineering/proxy-ssh-using-tls-sni...
    но это на мой "ngnix " не поставить - можно лишь как в вопросе
    внутренний ip/порт и выбор https|http

    в обоих случаях с sshd ничего не делают
    и всё равно не понимаю как ssh сервер понимает https ? или из прокси он уже чистым ssh выходит? но назад обратно в https заворачивается?
    Написано
  • SSH +reverse https proxy, при чём тут openSSL(VPN)?

    @Quqas Автор вопроса
    нигде в советах про ковыряние на стороне ssh сервера ни слова
    Написано
  • SSH +reverse https proxy, при чём тут openSSL(VPN)?

    @Quqas Автор вопроса
    Т.е. чтобы приведённый пример работал, нужно чтобы на целевом сервере на 443 порту крутился какой-то реверс-прокси (точнее, TLS termination proxy), который распакует трафик из туннеля и пробросит его на порт, который слушает SSH-сервер. Имхо, SSH-сервер про эти фокусы вообще ничего не знает.

    это выполняется
    reverse proxy настроен
    слушает 443 и направляет на 222

    но вот на счёт что "распаковывает" не уверен и наоборот имхо вредно, либо ещё один прокси нужен? помимо внешнего ещё и внутренний?

    советы(читал и больше)
    https://dev.to/udara_dananjaya/how-to-access-ssh-o...

    https://iyzico.engineering/proxy-ssh-using-tls-sni...
    Написано
  • SSH +reverse https proxy, при чём тут openSSL(VPN)?

    @Quqas Автор вопроса
    Vindicar, надо ковырять... и смотреть, может и можно отдельный порт с openssl сервером прикрутить. но точно что сам opensll ещё надо както туда поставить....

    т.е. в примерах из которых я подчерпнул метод - все эти советчики не говорили что у них сервер debian и поэтому ихний ssh из коробки понимал что делать когда на ssh порт долбится openssl?
    Написано
  • SSH +reverse https proxy, при чём тут openSSL(VPN)?

    @Quqas Автор вопроса
    AlexVWill,
    а не переводит трафик из протокола в протокол, из Https в SSH

    именно
    поэтому советы (а их в гугле не 1 и не 2 и разные люди =не копипаста) и вызывают вопросы и удивление.

    но как я понял именно часть команды про openssl превращает ssh в https
    Написано
  • SSH +reverse https proxy, при чём тут openSSL(VPN)?

    @Quqas Автор вопроса

    Что значит "только по HTTPS"?
    Но соответствие HTTPS может контролироваться более жёстко. Нужно использовать заданный хостером HTTP-прокси/реверс-прокси для работы с сетью? Или, скажем, слишком долго висящие соединения принудительно рвутся? Или TLS-хэндшейк проверяется на соответствие популярным браузерам? Во всех этих случаях простым туннелем ты не обойдёшься.

    встроенный в кинетик http туннель ихней облачной службы
    заведомо известно что если просто tcp поток то не летит
    сам tls client hello отслеживают чётко
    какое sni туда и попадает на внутренний адрес\порт
    и если на адресе-порте web всё ок
    а с ssh неясно. заведомо не веб

    openssl отдельно по sni как-будто попадает куда надо(т.е. на порт ssh), но не держит туннель - данных то нету+непонимаю с чего вдруг ssh сервер должен этот openssl понимать? я его не настраивал. и в примерах\советах тоже никто не настраивает а якобы сразу соединяются

    вся "надежда" что я не так пишу команду
    Написано
  • SSH +reverse https proxy, при чём тут openSSL(VPN)?

    @Quqas Автор вопроса
    обновил

    как можно сделать ещё понятней вам не понимаю сам
    Написано
  • SSH +reverse https proxy, при чём тут openSSL(VPN)?

    @Quqas Автор вопроса
    Dmitry, по ssh к серваку подключиться
    извне
    Написано
  • Можно ли настроить PuTTY, чтобы отображалось как в консоли?

    @Quqas Автор вопроса
    Кот Абсолютный, именно, но раз уже xterm а "тут" putty то пространство для манёвра?
    я с твоих же слов понял что putty=xterm only (вариации ***color не в счёт)
    Написано