저작권 안내: 저작권자표시 Yes 상업적이용 No 컨텐츠변경 No

스프링4 입문

스프링 4

DDD Start

객체 지향과
디자인 패턴

JSP 2.3

JPA 입문


"[팁] j2ssh-maverick를 이용한 SCP + 키이용 파일 복사"에서 SCP 복사를 위해 j2ssh-maverick를 이용했는데, j2ssh-maverick를 이용해서 SFTP 파일 다운로드도 처리했다. 메이븐 의존 설정은 동일하니 이전글을 참고하면 된다.


SFTP로 특정 폴더의 전체 파일을 다운로드받는 코드는 다음과 같다. 아이디, 암호를 이용해서 인증을 처리했는데, 키파일을 이용하고 싶다면 이전글을 참고한다.


String host = "원격서버";

int port = 22;

String remoteUser = "download";


SshClient ssh = null;

try {

    SshConnector con = SshConnector.createInstance();

    ssh = con.connect(new SocketTransport(host, port), remoteUser);

    Ssh2PasswordAuthentication auth = new Ssh2PasswordAuthentication();

    auth.setUsername(remoteUser);

    auth.setPassword(password);

    int authResult = ssh.authenticate(auth);

    if (authResult != SshAuthentication.COMPLETE) {

        throw new RuntimeException("authFail = " + authResult);

    }

    SftpClient sftp = new SftpClient(ssh);

    sftp.setTransferMode(SftpClient.MODE_BINARY);

    FileTransferProgress progress = createFileTransferProgress();

    sftp.copyRemoteDirectory(

            "/home/download/files", // 다운로드할 원격 서버 폴더

            "/data/local/files", // 복사할 파일을 저장할 로컬 폴더 경로

            false, // recursive: true면 하위 폴더까지 포함

            false, // sync: 동기화 여부, true면 원격 폴더에 존재하지 않는 파일을 삭제

            true, // commit: true면 실제 작업을 수행

            progress); // 진척도를 통지받을 객체

    sftp.exit();

} catch (SshException | IOException | SftpStatusException | ChannelOpenException

        | TransferCancelledException e) {

    logger.error("fail to download", e);

    throw new RuntimeException(e);

} finally {

    if (ssh != null)

        try {

            ssh.disconnect();

        } catch (Exception ex) {

        }

}


progress를 생성할 때 사용한 createFileTransferProgress() 메서드는 다음과 같다. FileTransferProgress를 알맞게 구현하면 파일을 얼마나 다운로드했는지 추적할 수 있다.


private FileTransferProgress createFileTransferProgress() {

    return new FileTransferProgress() {

        @Override

        public void started(long bytesTotal, String remoteFile) {

            logger.info("download start: {}", remoteFile);

        }


        @Override

        public void progressed(long bytesSoFar) {

        }


        @Override

        public boolean isCancelled() {

            return false;

        }


        @Override

        public void completed() {

            logger.info("download done");

        }

    };

}


j2ssh-maverick를 사용하면 폴더 뿐만 아니라 개별 파일에 대한 업로드, 다운로드도 처리할 수 있다. j2ssh-maverick가 제공하는 다양한 기능은 https://github.com/sshtools/j2ssh-maverick에서 확인할 수 있다.

저작자 표시 비영리 변경 금지
신고
Posted by 최범균 madvirus

댓글을 달아 주세요

페이스북 친구들과 댓글을 공유하고 싶다면 아래를 이용해주세요.

이번에 프로젝트를 진행하면서 자바 코드로 작성한 배치 처리 프로그램에서 SCP로 파일을 외부 서버로 전송할 일이 생겼다. 검색을 하고 몇 개를 훑어본 뒤에 j2ssh-maverick을 사용하기로 결정했다.


SCP 파일 복사에 사용할 key 파일 생성


ssh-keygen 명령어로 키 파일을 생성한다.


$ ssh-keygen -t rsa

Generating public/private rsa key pair.

Enter file in which to save the key (/home/madvirus/.ssh/id_rsa):

Created directory '/home/madvirus/.ssh'.

Enter passphrase (empty for no passphrase):

Enter same passphrase again:

Your identification has been saved in /home/madvirus/.ssh/id_rsa.

Your public key has been saved in /home/madvirus/.ssh/id_rsa.pub.

The key fingerprint is:

SHA256:....생략..... madvirus@mvpc

The key's randomart image is:

+---[RSA 2048]----+

|o. .+** .        |

|. ..=o =         |

|.o +.o. o        |

|. *o.o.  o       |

| ..Eo  .S        |

|+o= +   .        |

|+*.* +   .       |

|+.* *   .        |

|o*oo ...         |

+----[SHA256]-----+



명령어를 실행하고 나면 홈 디렉토리의 .ssh 폴더에 비밀키 id_rsa 파일과 공개키 id_rsa.pub 파일이 생성된다.


공개키 내용을 복사할 원격 서버의 authorized_keys 파일에 추가


SCP로 파일을 복사할 원격 서버 계정의 authorized_keys 파일에 공개키 파일을 추가한다. 원격 서버의 홈 디렉토리에 .ssh 디렉토리가 없다면 .ssh 디렉토리를 생성한다. 단 권한은 700으로 설정한다. ~/.ssh/authorized_keys 파일이 없다면 authorized_keys 파일도 생성한다. 이 파일의 권한은 600으로 설정한다.


-원격서버에 scp에 사용할 계정으로 로그인

$ cd ~

$ mkdir .ssh

$ chmod 700 .ssh

$ touch .ssh/authorized_keys

$ chmod 600 .ssh/authorized_keys


.ssh 폴더와 authorized_keys 파일의 권한이 올바르지 않으면 sshd는 SSH 연결을 허용하지 않는다. 이에 대한 내용은 http://man.openbsd.org/sshd를 참고한다.


원격 서버에 ~/.ssh 폴더와 ~/.ssh/authorized_keys 파일을 생성했다면 공개키 파일의 내용을 원격서버의 authorized_keys 파일에 추가한다. 아래 명령어를 사용하면 간편하게 추가할 수 있다.


cat ~/.ssh/id_rsa.pub | ssh 계정@원격서버주소 'cat >> ~/.ssh/authorized_keys'



프로젝트에 의존 추가


j2ssh-maverick을 사용하려면 다음의 의존을 pom.xml 파일에 추가한다.


<dependency>

    <groupId>com.sshtools</groupId>

    <artifactId>j2ssh-maverick</artifactId>

    <version>1.5.5</version>

</dependency>


j2ssh-maverick과 키 파일을 이용한 SCP 복사


앞서 생성한 비밀키 파일인 id_rsa를 이용해서 로컬의 파일을 원격지 서버에 전송하는 코드를 작성할 차례이다. 전체 코드는 다음과 같다.


File keyFilePath = new File("id_rsa 파일 경로");

String remoteHost = "원격서버주소";

String remoteUser = "batch";

File localFile = new File("전송할 로컬 파일");

String remotePath = "/home/batch/file";

SshClient ssh = null;

try {

    SshConnector con = SshConnector.createInstance();

    byte[] pkKey = FileCopyUtils.copyToByteArray(keyFilePath);

    SshPrivateKeyFile pkf = SshPrivateKeyFileFactory.parse(pkKey);

    SshKeyPair pair = pkf.toKeyPair("");


    ssh = con.connect(new SocketTransport(remoteHost, 22), remoteUser);


    Ssh2PublicKeyAuthentication sshAuth = new Ssh2PublicKeyAuthentication();

    sshAuth.setPrivateKey(pair.getPrivateKey());

    sshAuth.setPublicKey(pair.getPublicKey());

    int authResult = ssh.authenticate(sshAuth);


    if (authResult == SshAuthentication.COMPLETE) {

        ScpClient scpClient = new ScpClient(localFile, ssh);

        scpClient.put(localFile.getAbsolutePath(), remotePath, false);

        scpClient.exit();

    } else {

        // 인증에 실패한 경우, 알맞은 처리

    }

} finally {

    if (ssh != null)

        try {

            ssh.disconnect();

        } catch (Exception ex) {

        }

}


인증에 실패할 경우 원격서버의 .ssh 디렉토리 권한과 .ssh/authorized_keys 파일의 권한이 올바른지 확인해본다.


j2ssh-maverick에 대한 다양한 내용은 https://github.com/sshtools/j2ssh-maverick 사이트에서 확인할 수 있다.



저작자 표시 비영리 변경 금지
신고
Posted by 최범균 madvirus

댓글을 달아 주세요

페이스북 친구들과 댓글을 공유하고 싶다면 아래를 이용해주세요.

윈도우8 PC에 Virtualbox를 설치하고 게스트OS로 윈도우7을 생성했다. 그런데, 이상하게 윈도우7 머신에서 네트워크가 안 되는 문제가 발생했다. 그래서 Vagrant로 Centos 머신을 생성했다. 역시나 Centos 머신도 네트워크가 안 됐다. 포트포워딩 설정을 해도 Centos에 붙질 않았다.


Virtualbox와 Vagrant를 재설치해보고 보안 관련 프로그램도 살펴봤는데 영 문제가 해결되지 않앗다. 이래 저래 삽질을 하면서 증상은 다음과 같음을 알 수 있다.

  • 게스트OS에서 ping은 됨
  • 게스트OS에서 TCP 연결이 안 됨 (예, 윈도우 게스트OS에서 브라우저로 연결이 안 됨. telnet으로 외부 서비스에 특정 포트로 연결이 안 됨)

증상이 이상해서 범위를 좁혀서 구글에서 검색을 하다가 아래 명령어를 통해서 해결할 수 있음을 알아냈다.


netsh winsock reset


그런데, 이 명령어를 실행하고 나니 DB 보안 프로그램인 샤크라맥스가 동작하지 않았다. 실제 원인은 샤크라와 버추얼박스 간에 문제였던 것있다. 샤크라맥스를 언인스톨하고 다시 설치했더니 이제 샤크라맥스도 정상 실행되고 버추얼박스에 생성한 게스트OS의 네트워크도 정상 동작한다.


정확히는 모르지만 버추얼박스를 설치한 뒤에 샤크라를 설치해야 버추얼박스의 네트워크 기능이 정상 동작하는 듯 하다.

저작자 표시 비영리 변경 금지
신고
Posted by 최범균 madvirus

댓글을 달아 주세요

  1. 2017.06.21 09:25  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

페이스북 친구들과 댓글을 공유하고 싶다면 아래를 이용해주세요.

티스토리 툴바