読者です 読者をやめる 読者になる 読者になる

ITお絵かき修行

3歩歩いても忘れないために

JavaでTelnetクライアント作成・RHELにTelnetサーバ導入

JavaのSocketクラスを使ってTelnet接続してみる。
ついでにTelnetサーバを立てる手順も備忘録として残す。

【すること】
Telnet接続する。
※セッションモードで端末に接続し、コマンドが打てるところまで確認する。
 NVTとしての仕様は網羅しない。

【環境】
●OS
クライアント側:Windows7 64bit
サーバ側   :Red Hat Enterprise Linux Server release 7.1 (Maipo)

Java
1.8.0_60-b27


Telnetサーバ導入】
0.はじめに
・23番ポートを空ける。
Telnetを実行するユーザはスーパーユーザである必要があるため、rootユーザで接続確認する。
 Telnetプロトコルで使用するユーザ名とパスワードは平文で流れるので注意する。
[参考] ITエンジニアの「やってはいけない」 - [セキュリティ編]運用管理にtelnetを使ってはいけない:ITpro
・スーパーサーバであるxinetdを利用してTelnetサーバを管理する。
[参考] xinetd - Wikipedia


1.インストール(※rootユーザで行う)

yum update
yum install telnet -y
yum install telnet-server -y
yum install xinetd -y ※RHELには入ってないので入れておく

2.xinetdよりTelnetサーバ有効化

vi /etc/xinetd.d/telnet

●/etc/xinetd.d/telnet

service telnet
{
        flags           = REUSE
        socket_type     = stream
        wait            = no
        user            = root
        server          = /usr/sbin/in.telnetd
        log_on_failure  += USERID
        disable         = no ←「yes」から「no」へ変更し、有効化
}

3.xinetd起動および自動起動の設定
(※xinetdを起動することによりTelnetサーバも起動する)

service xinetd start
chkconfig --add xinetd
chkconfig xinetd on

インストール手順はここまで。


Telnet接続】
Telnet接続用クラス

package hhhhhskw.com;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
 * Telnet接続用クラス
 */
public class TelnetConnector {

	private final static int DEFAULT_TELNET_PORT = 23;

	private final static byte IAC = (byte) 255;
	private final static byte DONT = (byte) 254;
	private final static byte DO = (byte) 253;
	private final static byte WONT = (byte) 252;
	private final static byte WILL = (byte) 251;

	/**
	 * NVTとしてのネゴシエーションを行う
	 * @param os
	 * @param is
	 * @throws IOException
	 */
	private void negotiation(OutputStream os, BufferedInputStream is) throws IOException {
		byte[] buff = new byte[3];
		while (true) {
			is.mark(buff.length);
			if (is.available() >= buff.length) {
				is.read(buff);
				// ネゴシエーション完了
				if (buff[0] != IAC) {
					is.reset();
					return;
				// DOコマンドに対してWONTで返答する
				} else if (buff[1] == DO) {
					buff[1] = WONT;
					os.write(buff);
				}
			}
		}
	}

	/**
	 * 実行メソッド
	 * @param host
	 * @param port
	 */
	public void execute(String host, int port) {

		Socket socket = null;
		OutputStream os = null;
		BufferedInputStream is = null;

		try {
			socket = new Socket(host, port);
			os = socket.getOutputStream();
			is = new BufferedInputStream(socket.getInputStream());

			// 23番ポートへの接続の場合ネゴシエーションを行う
			if (port == DEFAULT_TELNET_PORT) {
				negotiation(os, is);
			}

			StreamConnector stdinToSocket = new StreamConnector(System.in, os);
			StreamConnector socketToStdout = new StreamConnector(is, System.out);

			Thread input = new Thread(stdinToSocket);
			Thread output = new Thread(socketToStdout);

			input.start();
			output.start();

		} catch (IOException e) {
			e.printStackTrace(System.out);
			System.err.println("接続中に例外が発生しました");
			System.exit(1);
			// コネクションはクローズしない
			// } finally {
			// try {
			// socket.close();
			// os.close();
			// is.close();
			// } catch (IOException e) {
			// }
		}
	}

	/**
	 * ストリームの読み書きクラス
	 */
	class StreamConnector implements Runnable {

		private InputStream is = null;
		private OutputStream os = null;

		public StreamConnector(InputStream in, OutputStream out) {
			this.is = in;
			this.os = out;

		}

		@Override
		public void run() {
			byte[] buff = new byte[1024];
			try {
				while (true) {
					int n = is.read(buff);
					if (n > 0) {
						os.write(buff, 0, n);
					}
				}
			} catch (IOException e) {
				e.printStackTrace(System.out);
				System.out.println("入出力の書き込み中に例外が発生しました");
				System.exit(1);
			}
		}
	}
}

● 実行クラス

package hhhhhskw.com;

public class TelnetMain {

	/**
	 * mainメソッド
	 * @param args 第一引数:ホスト名 第二引数:ポート番号
	 */
	public static void main(String[] args) {
		String host = args[0];
		int port = Integer.parseInt(args[1]);

		TelnetConnector tc = new TelnetConnector();
		tc.execute(host, port);
	}
}

●実行方法
第一引数にサーバのホスト名(IPアドレス)、第二引数にポート番号を指定し、実行する。

java hhhhhskw.com.TelnetMain (ホスト名orIPアドレス) 23

●実行結果

Kernel 3.10.0-229.el7.x86_64 on an x86_64
(サーバ名) login: root
root
Password: (パスワード)

Last login: Sat Sep  5 07:17:35 on pts/2
[root@ip-xxx-xxx-xxx-xxx ~]# ls -al
total 104
dr-xr-x---.  4 root root  4096 Aug 31 04:23 .
dr-xr-xr-x. 18 root root  4096 Aug 30 07:59 ..
-rw-------.  1 root root  9813 Feb 25  2015 anaconda-ks.cfg
-rw-------.  1 root root  1974 Aug 31 05:34 .bash_history
-rw-r--r--.  1 root root    18 Dec 28  2013 .bash_logout
-rw-r--r--.  1 root root   176 Dec 28  2013 .bash_profile
-rw-r--r--.  1 root root   176 Dec 28  2013 .bashrc
-rw-r--r--.  1 root root   100 Dec 28  2013 .cshrc
-rw-------   1 root root 45711 Sep  5 07:18 nohup.out
drwxr-----   3 root root    18 Aug 30 08:00 .pki
-rw-r--r--   1 root root  7154 Aug 31 02:27 ps.txt
drwx------.  2 root root    28 Aug 30 07:55 .ssh
-rw-r--r--.  1 root root   129 Dec 28  2013 .tcshrc
-rw-------   1 root root   759 Aug 31 04:23 .viminfo
[root@ip-xxx-xxx-xxx-xxx ~]#


【参考URL】
http://www.kg-group.com/JavaContent/Menu/TreeView5150_16/reference/j-network/Telnet.java
Telnetプログラム IT EngineerによるIT生活/ウェブリブログ
CentOSでtelnetできるようにするまでの手順(クライアント・サーバ) | Futurismo
UJP - 技術情報(dotforward.jp)