Własny serwer SSH i znak końca linii

0

Próbując rozwiązać problem opisany tu: Bezpieczna zdalna konsola CLI
Napisałem sobie własną konsolę CLI, do której można podłączyć się choćby telnetem, a teraz chciałem stworzyć własny serwer SSH, który po połączeniu będzie przenosił użytkownika do tej konsoli.
Poniżej najważniejsze rzeczy:

Konsola CLI po socketach:

	serverSocket = new ServerSocket(3001, lenghtOfQuere, InetAddress.getByName("localhost"));
			while (listening) {
				new RemoteConsoleHandler(serverSocket.accept()).start();
			}

			serverSocket.close();

oraz:

	public RemoteConsoleHandler(Socket s) {
		this.connection = s;
		setPrompt("geodet");
		commandStore = new CommandStore();
	}
public void run() {

		try {
			InetAddress adr = connection.getInetAddress();
			int remotePort = connection.getPort();
			log.debug("Rozpoczynam obsługę połączenia do konsoli zdalnej z adresu " + adr + " oraz portu " + remotePort);

			out = new PrintWriter(connection.getOutputStream(), true);
			in = new BufferedReader(new InputStreamReader(connection.getInputStream()));

			out.format("Naciśnij ENTER, żeby rozpocząć"); // jeśli użytkownik łączy się telnetem, to pierwszy komunikat zaczyna się od śmieci, więc warto go ominąć

			in.readLine();

			out.format(getPrompt());

			String command = in.readLine();
			if (command != null) {
				while (!command.equalsIgnoreCase("exit")) {
					if (command.length() > 0) {
						log.trace("Użytkownik " + adr.getHostName() + "/" + remotePort + " wydał polecenie: " + command);
						String answer = handleCommand(command);
						send(answer);
					}
					out.format(getPrompt());
					command = in.readLine();
				}
				log.debug("Rozłączam użytkownika połączonego z adresu " + adr + " oraz portu " + remotePort);
			}
			out.close();
			in.close();
			connection.close();
		} catch (NullPointerException e) {
			log.warn("Użytkownik rozłączył się niespodziewanie");
		} catch (Exception e) {
			log.error("Błąd zdalnej konsoli użytkownika", e);
		}
	}

Pomijam resztę, bo ta część działa pięknie. Gorzej z SSHD.

import org.apache.log4j.Logger;
import org.apache.sshd.SshServer;
import org.apache.sshd.server.PasswordAuthenticator;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.session.ServerSession;
import org.apache.sshd.server.shell.ProcessShellFactory;

public class TunnelSSH implements PasswordAuthenticator {

	private static final Logger log = Logger.getLogger("Tunel SSH dla konsoli zdalnej");

	public void openTunnel() {
		try {
			SshServer sshd = SshServer.setUpDefaultServer();
			sshd.setPort(3000));
			sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider("plik_z_kluczami"));
			sshd.setShellFactory(new ProcessShellFactory(new String[] { "telnet", "localhost", "3001"}));
			sshd.setPasswordAuthenticator(this);
			sshd.start();
		} catch (Exception e) {
			log.error("Nie mogę uruchomić bezpiecznego przekierowania dla portu konsoli zdalnej", e);

		}

	}

	public boolean authenticate(String userName, String password, ServerSession session) {
		return UserCache.checkUser(userName, password);
	}

Samo w sobie też działa. Próbowałem zamiast

sshd.setShellFactory(new ProcessShellFactory(new String[] { "telnet", "localhost", 3001 }));

wpisać

sshd.setShellFactory(new ProcessShellFactory(new String[] { "/bin/bash", "-i", "-l"}));

i wtedy mam dostęp do zwykłego basha.
Nie pisałbym tego wszystkiego, gdyby nie pewne "ale". Po podłączeniu poprzez SSH i uwierzytelnieniu dostaję albo basha, albo od razu połączenie ze swoją konsolą, jednak gubią mi się znaki powrotu karetki. Wpisuję polecenie i wszystko się przesuwa, tzn. kursor drukuje linijkę niżej, ale nie wraca do początku.

Oprócz tego w przypadku wywołania telneta po połączeniu (z basha lub zamiast basha) nie widzę w dodatku tego, co piszę, a moja konsola dostaje wpisany tekst z jakimiś białymi znakami, których nie potrafi czytać, ani nawet wyświetlić. Moje logowanie wyświetla wpisaną komendę i normalnie powinna być ona obsłużona, a jednak nie może jej porównać ze wzorcem (zwykły equalsIgnoreCase). Domyślam się, że telnet przeszedł w tryb character, a chyba nie powinien (http://fooworks.com/apache-mina-user/2011-09/msg00032.html), bo jak łączę się bezpośrednio z socketem na którym mam konsolę (bez SSH w roli pośrednika) i sam ustawiam w telnecie "mode character", to też nie widzę, co piszę i też mam białe znaki (choć nie wpływa to na powrót karetki).

Walczę z tym już od pewnego czasu, ale oficjalna dokumentacja od SSHD jest... hmmm... uboga, więc niezbyt mi się to udaje. Może ktoś miał taki problem lub ma pomysł, jak to ugryźć?

0

OK, działa.
Chodziło o ustawienie zmiennych definiujących zachowanie konsoli -> drukowanie komunikatów i postępowanie z końcem linii dla wejścia i wyjścia. Zamieniłem też telnet na nc, ale to już nie miało znaczenia. Konkretniej ustawiłem:

EnumSet<TtyOptions> enumSet = EnumSet.noneOf(TtyOptions.class);
enumSet.add(TtyOptions.Echo);
enumSet.add(TtyOptions.ONlCr);
enumSet.add(TtyOptions.ICrNl);
sshd.setShellFactory(new ProcessShellFactory(new String[] { "nc", "localhost", ServerProperties.getProperty("console_port") }, enumSet));

1 użytkowników online, w tym zalogowanych: 0, gości: 1