ラベル SSH の投稿を表示しています。 すべての投稿を表示
ラベル SSH の投稿を表示しています。 すべての投稿を表示

2019年7月15日月曜日

android AsyncTaskによるJSchを用いたSSH通信とAsyncTask内イベントの呼び出し元クラスでのキャッチ

2019 Jul. 15.

MyJsch.java
package your.package;

import android.content.Context;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.UserInfo;

import java.io.File;
import java.io.InputStream;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;

class MyJsch {
    private final String ServerIp;
    private final int Port;
    private final String User;
    private final String PassPhraseWord;
    private final String IdentityKeyPath;
    private final Context AppContext;

    /** Channel接続タイプ */
    private static final String CHANNEL_TYPE = "sftp";

    /*
     * コンストラクタ
     */
    MyJsch( final String ServerIp, final int Port, final String User, final String PassPhraseWord,
            final String IdentityKeyPath, final Context AppContext) {
        this.ServerIp = ServerIp;
        this.Port = Port;
        this.User = User;
        this.PassPhraseWord = PassPhraseWord;
        this.IdentityKeyPath = IdentityKeyPath;
        this.AppContext = AppContext;
    }


    /*
     * Sessionを開始
     */
    protected Session connectSession() throws JSchException {
        Session session = null;

        // android端末内の外部ストーリッジ確認
        List sdCardFilesDirPaths =
                SdCardDirPaths.getSdCardFilesDirPathListForLollipop( AppContext );
        Collections.sort(sdCardFilesDirPaths, new CompStringLength());
        String externalPath = sdCardFilesDirPaths.get(0);
        externalPath = externalPath.replaceAll("/Android.*$", "");

        final JSch jsch = new JSch();

        // クライアント側のknownHostsチェックを行わない
        Hashtable config = new Hashtable();
        config.put("StrictHostKeyChecking", "no");
        jsch.setConfig(config);

        // パスフレーズ・秘密鍵方式
        String privKeyFilePath = externalPath + "/" + IdentityKeyPath;
        File privKeyFile = new File(privKeyFilePath);
        if (privKeyFile.exists() ) {
            jsch.addIdentity(privKeyFilePath, PassPhraseWord);
        }

        // Session取得
        session = jsch.getSession(User, ServerIp, Port);

        // パスワード方式でも可とする
        session.setPassword(PassPhraseWord);

        final UserInfo userInfo = new SftpUserInfo();
        session.setUserInfo(userInfo);
        session.connect();
        return session;
    }


    /**
     * SFTPのChannelを開始
     *
     * @param session
     *            開始されたSession情報
     */
    protected ChannelSftp connectChannelSftp(final Session session)
            throws JSchException {
        final ChannelSftp channel = (ChannelSftp) session.openChannel(CHANNEL_TYPE);
        try {
            channel.connect();
        } catch (JSchException e) {
            return null;
        }
        return channel;
    }


    /**
     * Session・Channelの終了
     *
     * @param session
     *            開始されたSession情報
     * @param channels
     *            開始されたChannel情報.複数指定可能
     */
    protected void disconnect(final Session session, final Channel... channels) {
        if (channels != null) {
            for (Channel c: channels ) {
                if (c != null) {
                    c.disconnect();
                }
            }
        }
        if (session != null) {
            session.disconnect();
        }
    }


    /**
     * SFTPに接続するユーザ情報を保持するクラス
     */
    private static class SftpUserInfo implements UserInfo {
        @Override
        public String getPassword() {
            return null;
        }
        @Override
        public boolean promptPassword(String arg0) {
            return true;
        }
        @Override
        public boolean promptPassphrase(String arg0) {
            return true;
        }
        @Override
        public boolean promptYesNo(String arg0) {
            return true;
        }
        @Override
        public void showMessage(String arg0) {
        }
        @Override
        public String getPassphrase() {
            return null;
        }
    }


    /**
     * ファイルアップロード
     *
     * @throws JSchException
     *             Session・Channelの設定/接続エラー時に発生
     */
    public void putFile(ChannelSftp channel, InputStream inStream, String destPath)
            throws SftpException {

        /*
         * sftp通信を実行
         */
        String absoluteDestPath = channel.getHome() + "/" + destPath;
        String destFile = new File(absoluteDestPath).getName();
        int numDestPath = absoluteDestPath.length();
        int numDestFile = destFile.length();
        String destParentPath = absoluteDestPath.substring( 0, numDestPath - numDestFile );
        channel.cd(destParentPath);
        channel.put( inStream, destFile);

        // confirm existance of destFile
        channel.lstat(destFile);
    }

    /*
     * サーバー上のファイルの削除
     *   destFileNameFront文字列から始まるファイルを全て削除する
    */
    public void deleteFiles(ChannelSftp channel, String destFileNameFront) throws SftpException {
        channel.rm(destFileNameFront + "*");
    }
}

SdCardDirPaths.java
package your.package;

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Environment;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class SdCardDirPaths {

    /**
     * SDカードのfilesディレクトリパスのリストを取得する。
     * Android5.0以上対応。
     *
     * @param context
     * @return SDカードのfilesディレクトリパスのリスト
     */
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public static List getSdCardFilesDirPathListForLollipop(Context context) {
        List sdCardFilesDirPathList = new ArrayList<>();

        // getExternalFilesDirsはAndroid4.4から利用できるAPI。
        // filesディレクトリのリストを取得できる。
        File[] dirArr = context.getExternalFilesDirs(null);


        for (File dir : dirArr) {
            if (dir != null) {
                String path = dir.getAbsolutePath();

                // isExternalStorageRemovableはAndroid5.0から利用できるAPI。
                // 取り外し可能かどうか(SDカードかどうか)を判定している。
                if (Environment.isExternalStorageRemovable(dir)) {

                    // 取り外し可能であればSDカード。
                    // このパスをパスリストに加える
                    if (!sdCardFilesDirPathList.contains(path)) {
                        sdCardFilesDirPathList.add(path);
                    }
                }
            }
        }
        return sdCardFilesDirPathList;
    }
}

(利用例)
Send2ServerTask.java
package your.package;

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

// 複数のファイルをSSH送信する
public class Send2ServerTask extends AsyncTask {
    final String ServerIp = "SSH.SERVER.IP.ADDRESS";
    final int Port = 22;
    final String User = "SshLogInUser";
    final String IdentityKeyPath = "PRIVATE/KEY/FILE/PATH/IN/CLIENT/DEVICE";
    //     if IdentityKeyPath is illegal, password authentication is used.
    final String DestParentPath = "SERVER/DIR/TO/BE/STORED";

    private WeakReference weakRef;
    private HashMap inStreamMap;
    final private String passPhrase;
    final private String fileNameFront;
      // SSH失敗時のファイル削除のためにファイル名共通文字列を保持
      // 複数の送信ファイルはいずれもfileNameFront文字列で始まるファイル名とすること

    private Listener listener;

    /*
     * constructor
     *   inStreamMap 送信する複数ファイルのファイル名とインプットストリームをHashMapで渡す
     */
    Send2ServerTask(Activity parentActivity, HashMap inStreamMap,
                    String passPhrase, String fileNameFront) {
        weakRef = new WeakReference<>(parentActivity);
        this.inStreamMap = new HashMap<>(inStreamMap);
        this.passPhrase = passPhrase;
        this.fileNameFront = fileNameFront;
    }


    @Override
    protected String doInBackground(Void... params) {
        MyJsch mJsch;
        Session sftpSession = null;
        ChannelSftp sftpChannel = null;

        Activity refActivity = weakRef.get();
        if (refActivity == null || refActivity.isFinishing()) {
            return null;
        }

        Context appContext = weakRef.get().getApplicationContext();

        // initialise Jsch
        mJsch = new MyJsch(ServerIp, Port, User, passPhrase, IdentityKeyPath, appContext);

        // connect session, channel
        try {
            sftpSession = mJsch.connectSession();
            sftpChannel = mJsch.connectChannelSftp( sftpSession );

            // upload
            int count = 0;
            for ( Map.Entry entry : inStreamMap.entrySet()) {
                // entry.getKey()    entry.getValue()
                String destPath = DestParentPath + "/" + entry.getKey();
                try {
                    mJsch.putFile(sftpChannel, entry.getValue(), destPath);
                } catch (SftpException e) {
                    try {
                        // このセッションでアップロードされたファイルをすべて削除する
                        mJsch.deleteFiles(sftpChannel, fileNameFront);
                        mJsch.disconnect( sftpSession, sftpChannel);
                        return "Failed to upload files. count: " + count + ". " + destPath + " "  + e.toString();
                    } catch (SftpException e1) {
                        mJsch.disconnect( sftpSession, sftpChannel);
                        return "Failed to delete remote files. " + e1.toString();
                    }
                }

                try {
                    // take sleep between SFTP#puts
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    // このセッションでアップロードされたファイルをすべて削除する
                    mJsch.deleteFiles(sftpChannel, fileNameFront);
                    mJsch.disconnect( sftpSession, sftpChannel);
                    return "Failed! sleep" + e.toString();
                }
                count++;
            }
            if ( count != inStreamMap.size()) {
                // このセッションでアップロードされたファイルをすべて削除する
                mJsch.deleteFiles(sftpChannel, fileNameFront);
                mJsch.disconnect( sftpSession, sftpChannel);
                return "Could not upload " + inStreamMap.size() + " files";
            }
        } catch (JSchException | SftpException e) {
            mJsch.disconnect( sftpSession, sftpChannel);
            return "connection failed. " + e.toString();

        } finally {
            // disconnect channel, session
            mJsch.disconnect( sftpSession, sftpChannel);
        }
        return "Succeeded. " + inStreamMap.size() + " files upload";
    }


    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);

        Activity refActivity = weakRef.get();
        if (refActivity == null || listener == null)  {
            Toast.makeText(refActivity, "failed sending to server.", Toast.LENGTH_LONG).show();
        } else {
            if ( result.contains("Succeeded") ) {
                Toast.makeText(refActivity, result, Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(refActivity, result, Toast.LENGTH_LONG).show();
            }
            listener.onSuccess(result);
        }
        return;
    }

    void setListener(Listener listener) {
        this.listener = listener;
    }

    interface Listener {
        void onSuccess(String str);
    }
}

MyActivity.java
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_confirm_before_send);
        buttonOK = findViewById(R.id.buttonOK);
        setListeners();
    }

    /*
     * Send2ServerTaskへのリスナ
     *   サーバーへのアップロード終了後に行う処理を記述
     */
    private Send2ServerTask.Listener createListener() {
        return new Send2ServerTask.Listener() {
            @Override
            public void onSuccess(String result) {
                deleteFiles();
            }
        };
    }

    protected void setListeners(){
        buttonOK.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /*
                 * HashMap SSHサーバーに送るデータ
                 *   String 送信先ファイルパス
                 *   InputStream 送信ファイルのインプットストリーム
                 */
                HashMap dataMap = new HashMap<>();

                setData2dataMap(); // dataMapにSSH通信データをセットする
                setPassPhraseWord();
                setFileNameFront();

                /*
                 * dataMapを保管サーバーに送る
                 */
                send2serverTask = new Send2ServerTask(thisActivity, dataMap, passPhraseWord, fileNameFront);

                // Listenerを設定し、send2serverTaskを実行してdataMapを保管サーバーに送る
                send2serverTask.setListener(createListener());
                send2serverTask.execute();
            }
        });
    }

xrea SSH通信許可設定

2019 Jul. 15.

  1. xreaにログイン
  2. 旧コントロールパネルを表示
  3. 管理メニュー -> ホスト情報登録
  4. 「SSH登録」をクリック

2019年5月2日木曜日

JAVA JSch SFTP AndroidクライアントからSSHサーバーへのファイル転送

2019 May. 03.
2019 May. 02.

https://qiita.com/nenokido2000/items/a00348c9f6a0f942773b より




MainActivity.java

package YOUR.PACKAGE.NAME;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {


    /** Channel接続タイプ */
    private static final String CHANNEL_TYPE = "sftp";

    private MyTask task;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        /*
        final String ServerIP = "ServerIP";
        final int Port = PortNum;
        final String UserId = "USER";
        final String PassPhrase = "YOURPASSPHRASE";
        final String IdentityKeyPath = "YOUR/SECRET/FILE/PATH"; // Do not attach '/' at head of path
        final String SourcePath = "PATH/TO/SOURCE/FILE"; // Do not attach '/' at head of path
        final String DestPath = "PATH/TO/DEST/FILE";
        */

        final String ServerIP="";
        final int Port = ;
        final String UserId = "";
        final String PassPhrase = "";
        final String IdentityKeyPath = "";
        final String SourcePath = "";
        final String DestPath = "";

        Button button1= (Button) findViewById(R.id.button1);
        TextView textView1 = (TextView) findViewById(R.id.textView1);

        // タスクの生成
        task = new MyTask(ServerIP, Port, UserId, PassPhrase, IdentityKeyPath, SourcePath, DestPath,this);

        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                v.setEnabled(false);
                // 非同期処理を開始する
                task.execute();
            }
        });
    }
}


MyTask.java
package YOUR.PACKAGE.NAME;
import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.TextView;

import com.jcraft.jsch.JSchException;

import java.lang.ref.WeakReference;

public class MyTask extends AsyncTask {
    private final String ServerIp;
    private final int Port;
    private final String User;
    private final String IdentityKeyPath;
    private final String PassPhrase;
    private final String SrcPath;
    private final String DestPath;

    private WeakReference weakReference;


    // constructor
    MyTask(final String ServerIp, final int Port, final String User,
                  final String PassPhrase, final String IdentityKeyPath, final String SrcPath,
                  final String DestPath, Context referenceContext) {
        super();

        // 呼び出し元へのweakReference
        weakReference = new WeakReference<>(referenceContext);

        this.ServerIp = ServerIp;
        this.Port = Port;
        this.User = User;
        this.PassPhrase = PassPhrase;
        this.IdentityKeyPath = IdentityKeyPath;
        this.SrcPath = SrcPath;
        this.DestPath = DestPath;
    }



    /**
     * バックグランドで行う処理
     */
    @Override
    protected String doInBackground(Void... value) {
        // startJsch
        MyJsch mJsch = new MyJsch( ServerIp, Port, User, PassPhrase, IdentityKeyPath, SrcPath,
                DestPath, weakReference.get());
        try {
            mJsch.putFile();
        } catch (JSchException e) {
            e.printStackTrace();
            return e.toString();
        }
        return "Success";
    }


    /**
     * バックグランド処理が完了し、UIスレッドに反映する
     */
    @Override
    protected void onPostExecute(String result) {

        // get a reference to the activity if it is still there
        Activity activity = (Activity) weakReference.get();
        if (activity == null || activity.isFinishing()) return;

        activity.findViewById(R.id.button1).setEnabled(true);
        TextView tv = activity.findViewById(R.id.textView1);
        tv.setText(result);
    }

}


MyJsch.java
package YOUR.PACKAGE.NAME;
import android.content.Context;
import android.util.Log;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.UserInfo;

import java.io.File;
import java.util.Collections;
import java.util.List;

public class MyJsch {
    private final String ServerIp;
    private final int Port;
    private final String User;
    private final String PassPhrase;
    private final String IdentityKeyPath;
    private final String SrcPath;
    private final String DestPath;
    private Context activityContext;

    private String externalPath;

    /** Channel接続タイプ */
    private static final String CHANNEL_TYPE = "sftp";

    /**
     * コンストラクタ
     */
    MyJsch(final String ServerIp, final int Port, final String User, final String PassPhrase,
           final String IdentityKeyPath, final String SrcPath, final String DestPath,
           Context activityContext) {
        this.ServerIp = ServerIp;
        this.Port = Port;
        this.User = User;
        this.IdentityKeyPath = IdentityKeyPath;
        this.PassPhrase = PassPhrase;
        this.SrcPath = SrcPath;
        this.DestPath = DestPath;
        this.activityContext = activityContext;
    }


    /**
     * ファイルアップロード
     *
     * @throws JSchException
     *             Session・Channelの設定/接続エラー時に発生
     */
    public void putFile()
            throws JSchException {

        Session session = null;
        ChannelSftp channel = null;


        // 外部ストーリッジ確認
        List sdCardFilesDirPaths =
                SdCardDirPaths.getSdCardFilesDirPathListForLollipop( activityContext );
        Collections.sort(sdCardFilesDirPaths, new CompStringLength());
        for (String p : sdCardFilesDirPaths) {
            Log.d("My", "SDパスの1つ: " + p);
        }
        externalPath = sdCardFilesDirPaths.get(0);
        externalPath = externalPath.replaceAll("/Android.*$", "");
        Log.d("My", "SDパス: " + externalPath);

        // get sourcePath
        final String sourcePath = externalPath + "/" + SrcPath;
        Log.d("My", "sourcePath " + sourcePath );
        if ( new File(sourcePath).exists()) {
            Log.d("My", sourcePath + " exists.");
        } else {
            Log.d("My", sourcePath + " not exist.");
        }

        /*
         * sftp通信を実行
        */
        try {
            session = connectSession();
            channel = connectChannelSftp(session);

            String absoluteDestPath = channel.getHome() + "/" + DestPath;
            String destFile = new File(absoluteDestPath).getName();
            int numDestPath = absoluteDestPath.length();
            int numDestFile = destFile.length();
            String destParentPath = absoluteDestPath.substring( 0, numDestPath - numDestFile );

            Log.d("My", "absoluteDestPath is " + absoluteDestPath);
            Log.d("My", "destFile is " + destFile);
            Log.d("My", "destParentPath is " + destParentPath);
            Log.d("My", "current local directory is " + channel.lpwd());
            Log.d("My", "remote home directory is " + channel.getHome());

            channel.cd(destParentPath);
            channel.put(sourcePath, destFile);


            try {
                channel.lstat(destFile);
            } catch (SftpException e) {
                Log.d("My", DestPath + " does not exist.");
                Log.d("My", e.toString());
            }

        } catch (SftpException e) {
            Log.d("My",e.toString());
        } finally {
            disconnect(session, channel);
        }
    }

    /**
     * Sessionを開始
     */
    private Session connectSession()
            throws JSchException {

        final JSch jsch = new JSch();

        // 鍵追加
        String keyFilePath = externalPath + "/" + IdentityKeyPath;
        if ( new File(keyFilePath).exists()) {
            Log.d("My",  keyFilePath + " exists.");

        } else {
            Log.d("My",  keyFilePath + " not exist.");
        }

        jsch.addIdentity(keyFilePath, PassPhrase);

        // Session設定
        final Session session = jsch.getSession(User, ServerIp, Port);
        final UserInfo userInfo = new SftpUserInfo();

        // TODO 今回は使用しないがパスフレーズ等が必要な場合はUserInfoインスタンス経由で設定する

        session.setUserInfo(userInfo);

        session.connect();

        return session;
    }

    /**
     * SFTPのChannelを開始
     *
     * @param session
     *            開始されたSession情報
     */
    private ChannelSftp connectChannelSftp(final Session session)
            throws JSchException {
        final ChannelSftp channel = (ChannelSftp) session.openChannel(CHANNEL_TYPE);
        try {
            channel.connect();

        } catch (JSchException e) {
            Log.d("My",   e.toString());
        }
        return channel;
    }


    /**
     * Session・Channelの終了
     *
     * @param session
     *            開始されたSession情報
     * @param channels
     *            開始されたChannel情報.複数指定可能
     */
    private void disconnect(final Session session, final Channel... channels) {
        if (channels != null) {
            for (Channel c: channels ) {
                if (c != null) {
                    c.disconnect();
                }
            }
        }
        if (session != null) {
            session.disconnect();
        }
    }

    /**
     * SFTPに接続するユーザ情報を保持するクラス
     */
    private static class SftpUserInfo implements UserInfo {

        @Override
        public String getPassword() {
            return null;
        }

        @Override
        public boolean promptPassword(String arg0) {
            return true;
        }

        @Override
        public boolean promptPassphrase(String arg0) {
            return true;
        }

        @Override
        public boolean promptYesNo(String arg0) {
            return true;
        }

        @Override
        public void showMessage(String arg0) {
        }

        @Override
        public String getPassphrase() {
            return null;
        }
    }
}

JAVA JSch sftp sshサーバーへのファイル転送時のサーバー側ディレクトリ・ファイルの指定要領

2019 May 02.

sftp接続後、サーバーのカレントディレクトリを転送先ディレクトリに変更(ChannelSftp#cd)した上で、ファイル転送する。
ファイル転送コマンド(ChannelSftp#put)内でパスを記述できない。

2019年2月2日土曜日

JAVA SSHサーバーとの間で公開鍵認証でファイルをやり取りする

2019 Feb. 02.

https://qiita.com/nenokido2000/items/a00348c9f6a0f942773b より


import com.jcraft.jsch.*;
import java.util.Arrays;
import java.util.Hashtable;
public class Main {

    /** Channel接続タイプ */
    private static final String CHANNEL_TYPE = "sftp";

    /**
     * ファイルアップロード
     *
     * @param hostname
     *            接続先ホスト
     * @param port
     *            接続先ポート
     * @param userId
     *            接続するユーザ
     * @param identityKeyFileName
     *            鍵ファイル名
     * @param sourcePath
     *            アップロード対象ファイルのパス<br>
     *            アプリ実行環境上の絶対パスを指定
     * @param destPath
     *            アップ先のパス
     * @throws JSchException
     *             Session・Channelの設定/接続エラー時に発生
     * @throws SftpException
     *             sftp操作失敗時に発生
     */
    public void putFile(final String hostname, final int port,
                        final String userId, final String identityKeyFileName,
                        final String passPhrase,
                        final String sourcePath, final String destPath,
                        final String remotePath, final String localPath)
            throws JSchException, SftpException {

        Session session = null;
        ChannelSftp channel = null;

        try {
            session = connectSession(hostname, port, userId, identityKeyFileName, passPhrase);
            channel = connectChannelSftp(session);
            channel.put(sourcePath, destPath);
            channel.get(remotePath, localPath);
        } finally {
            disconnect(session, channel);
        }
    }

    /**
     * Sessionを開始
     *
     * @param hostname
     *            接続先ホスト
     * @param port
     *            接続先ポート
     * @param userId
     *            接続するユーザ
     * @param identityKeyFileName
     *            鍵ファイル名
     */
    private Session connectSession(final String hostname, final int port,
                                   final String userId, final String identityKeyFileName,
                                   final String passPhrase)
            throws JSchException {

        final JSch jsch = new JSch();

        // HostKeyチェックを行わない
        Hashtable config = new Hashtable();
        config.put("StrictHostKeyChecking", "no");
        jsch.setConfig(config);

        // 鍵追加
        jsch.addIdentity(identityKeyFileName, passPhrase );

        // Session設定
        final Session session = jsch.getSession(userId, hostname, port);
        final UserInfo userInfo = new SftpUserInfo();

        // TODO 今回は使用しないがパスフレーズ等が必要な場合はUserInfoインスタンス経由で設定する

        session.setUserInfo(userInfo);

        session.connect();

        return session;
    }

    /**
     * SFTPのChannelを開始
     *
     * @param session
     *            開始されたSession情報
     */
    private ChannelSftp connectChannelSftp(final Session session)
            throws JSchException {
        final ChannelSftp channel = (ChannelSftp) session
                .openChannel(CHANNEL_TYPE);
        channel.connect();

        return channel;
    }

    /**
     * Session・Channelの終了
     *
     * @param session
     *            開始されたSession情報
     * @param channels
     *            開始されたChannel情報.複数指定可能
     */
    private void disconnect(final Session session, final Channel... channels) {
        if (channels != null) {
            Arrays.stream(channels).forEach(c -> {
                if (c != null) {
                    c.disconnect();
                }
            });
        }
        if (session != null) {
            session.disconnect();
        }
    }

    /**
     * SFTPに接続するユーザ情報を保持するクラス
    */
    private static class SftpUserInfo implements UserInfo {

        @Override
        public String getPassword() {
            return null;
        }

        @Override
        public boolean promptPassword(String arg0) {
            return true;
        }

        @Override
        public boolean promptPassphrase(String arg0) {
            return true;
        }

        @Override
        public boolean promptYesNo(String arg0) {
            return true;
        }

        @Override
        public void showMessage(String arg0) {
        }

        @Override
        public String getPassphrase() {
            return null;
        }
    }


    public static void main(String[] args) throws JSchException, SftpException {

        String Hostname="SSH-SERVER-IP-ADDRESS";
        int Port=22;
        String UserId="USER";
        String PassPhrase = "YOUR-PASSPHRASE";
        String IdentityKeyFileName=System.getProperty("user.home")+"/PRIVATEKEY";
        String SourcePath=System.getProperty("user.home")+"/PATH/TO/FILE";
        String DestPath="PATH/TO/DESTFILE";
        String RemotePath="PATH/TO/REMOTEFILE";
        String LocalPath=System.getProperty("user.home")+"/ANOTHER/PATH/TO/FILE";

        final Main sftp = new Main();
        sftp.putFile(Hostname, Port, UserId, IdentityKeyFileName, PassPhrase,
                SourcePath, DestPath, RemotePath, LocalPath);
    }
}

2018年8月19日日曜日

BitbucketへのSSH認証導入

2018 Aug. 19.
 
$ cd ~/.ssh
$ mkdir bitbucket
$ cd bitbucket
$ ssh-keygen -t rsa -C YourMail@Address
 Enter file in which to save the key の問いに ~/.ssh/bitbucket/id_rsa と入力する。
 パスワードの設定を2回問われるが、Enterのみを入力する。
  
$ mv id_rsa id_rsa.bitbucket
$ chmod 600 id_rsa.bitbucket

~/.ssh/config に次を記載する
 Host bitbucket.org
  HostName bitbucket.org
  IdentityFile ~/.ssh/bitbucket/id_rsa.bitbucket
  User git
  Port 22
  TCPKeepAlive yes
  IdentitiesOnly yes
 
https://bitbucket.org にアクセスし、
「Manage Account」→「SSH keys」→「Add Key」と鍵設定画面に移る。
 Label:任意の文字列(クライアントデバイス名とか)
 Key:「id_rsa.bitbucket.org.pubの内容(メールアドレスを含む)」コピー&ペースト
 「鍵追加」ボタンを押す。

接続テスト
$ ssh -T git@bitbucket.org
(表示) 
 conq: logged in as ユーザ名.
You can use git or hg to connect to bitbucket. Shell access is disabled.
 
それまでhttps/sslで認証していたリポジトリは削除して再クローンを要するみたい。
 

2018年5月21日月曜日

2018年1月20日土曜日

SSH known_hostsファイル関連で Connection refused

2018 Sep. 01.

2018 Jan. 20.

$ ssh-keygen -R SERVER-ADDRESS
を実行する。
SERVER-ADDRESSはホスト名ではなくIPアドレスを指定する。
-R hostname
  Removes all keys belonging to hostname from a known_hosts file.
  This option is useful to delete hashed hosts (see the -H option
  above).

2016年12月10日土曜日

SSHで1度入れたパスフレーズをその後は尋ねられないようにする

2016 Dec. 10.

qiita.com/naoki_mochizuki/items/93ee2643a4c6ab0a20f5
webos-goodies.jp/archives/50672669.html より


$ ssh-add (パスフレーズを尋ねられるので入力する)
$ ssh SERVER

SSH "Are you sure you want to continue connecting"表示をなくす


2016 Dec. 10.

d.hatena.ne.jp/yohei-a/20100214/1266112027 より

sshクライアント側の /etc/ssh/ssh_config のStrictHostKeyChecking設定をnoにする。(ask/yes/noを設定できる)
  StrictHostKeyChecking no

$ man ssh_config
...
     StrictHostKeyChecking
             If this flag is set to ``yes'', ssh(1) will never automatically
             add host keys to the ~/.ssh/known_hosts file, and refuses to con-
             nect to hosts whose host key has changed.  This provides maximum
             protection against trojan horse attacks, though it can be annoy-
             ing when the /etc/ssh_known_hosts file is poorly maintained or
             when connections to new hosts are frequently made.  This option
             forces the user to manually add all new hosts.  If this flag is
             set to ``no'', ssh will automatically add new host keys to the
             user known hosts files.  If this flag is set to ``ask'', new host
             keys will be added to the user known host files only after the
             user has confirmed that is what they really want to do, and ssh
             will refuse to connect to hosts whose host key has changed.  The
             host keys of known hosts will be verified automatically in all
             cases.  The argument must be ``yes'', ``no'', or ``ask''.  The
             default is ``ask''.

2016年12月3日土曜日

sshサーバ インストール


2019 Oct. 12.
2018 Sep. 01.
2017 Feb. 12.
2017 Feb. 11.
2016 Dec. 03.

鍵ファイルについて

公開鍵

ファイルパス SERVER: ~/.ssh/id_rsa.pub

サーバーの authorized_keys に追記したら以後不要なので削除する。

秘密鍵

ファイルパス CLEINT: ~/.ssh/id_rsa
 このファイル名を変更した場合は、ssh接続時に
  $ ssh –i ~/.ssh/CLIENT-FILE
 と -i オプションを付ける。

 known_hostsファイル

ファイル名  CLEINT: ~/.ssh/known_hosts
接続したことのあるSSHサーバ証明書が格納されるファイル。

暗号種類

現時点の高強度順
edf25519
ecdsa 521bit
ecdsa 384bit
ecdsa 256bit
rsa 4096bit

DSA  SSH2で使える。 鍵長が1024bit。
RSA1 非推奨。脆弱性があるSSH1で使える。

クライアントが利用できる暗号にする。

時とともに古い方式となるので、時々見直す。

鍵生成

$ ssh-keygen -t 暗号方式 -b bit長 -C "コメント" -f ファイル名 -P "パスフレーズ"
  -f:ファイル名には拡張子を付けない。秘密鍵と公開鍵のペアが作られる。

(例)
$ ssh-keygen -t ed25519
$ ssh-keygen -t ecdsa -b 521
$ ssh-keygen -t ecdsa -b 384
$ ssh-keygen -t ecdsa -b 256

$ ssh-keygen -t rsa -b 4096

失くした公開鍵復元
$ ssh-keygen -yf 秘密鍵名



インストール

# apt install ssh


/etc/ssh/sshd_config を編集
    RSAAuthentication yes
    PubkeyAuthentication yes
    AuthorizedKeysFile      %h/.ssh/authorized_keys
    AllowUsers USER
    PermitRootLogin no
    PermitEmptyPasswords no
    PasswordAuthentication no

/etc/hosts.allow を編集
    sshd: ALL

# ufw enable
# ufw allow 22/tcp
# ufw allow 22/udp
# ufw reload

サーバーの ~/.ssh 内に公開鍵を配置する。
  $ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
  $ rm ~/.ssh/id_rsa.pub
  $ chmod 750 ~/
  $ chmod 700 ~/.ssh
  $ chmod 600 id_rsa authorized_keys

id_rsa をクライアントの各ソフトに合致する場所に置く。
 linuxならば ~/.ssh/ に。
  クライアント設定
   /etc/ssh/ssh_config
    RSAAuthentication yes
    IdentityFile ~/.ssh/id_rsa

 connect botならばSDカード内の任意のフォルダに。
  connect botの鍵設定は fnya.cocolog-nifty.com/blog/2012/03/connectbot-andr.html を参照。

# systemctl restart sshd