技術スタック インフラネットワーク

FTPクライアントでなくターミナルでsshやscpによる通信を行う方法

2020.07.31

こんにちはjunです。あなたはサーバー上にファイルをアップロードする際にどうやっていますか?大体がFTPクライアント(windowsだとwinscp、MacだとFileZillaなど)を使用していると思います。

GUIで操作できるソフトは扱いやすく、簡単にアップロード・ダウンロードを行ったり、複数ファイルを移動する際などは便利です。しかしある程度エンジニアレベルが上がると、サーバー構築やサーバー上での操作、例えば権限のいるファイルの編集とか機械的なファイル操作が必要になってくるので、FTPクライアントでの操作では限界が生じます。

特に大量のファイルを扱う際にはGUIクライアントソフトを用いると時間がかかったりすることも多かったり、権限によってファイルの操作ができない場合はsudoを打てる環境を用意しないといけません。

今回の記事ではSSHでサーバーとのやりとりをするための設定、そしてローカルとリモート間のscpを用いたファイル転送などGUIからCLI操作へのステップアップできるように解説していきたいと思います

前提条件

細かい説明に入る前に以下の条件での説明とします。

クライアント

  • macOS Catalina 10.15.5
  • ターミナルを使用

サーバー(GMO VPSとします)

  • centOS7
  • 22番ポート開放済み
  • sshdインストール済み

用語や基礎知識の確認

まず以降の説明を行う前に基礎的な用語と知識の解説を行います。知っている人はフンフンと頷きながら飛ばしてください。

SSH

Secure Shellのこと。直訳すると「安全なシェル」。シェルというのはターミナルとかコマンドプロンプトのことだと思ってください。そのシェルとネットワークを用いて遠隔にあるサーバーを操作します。昔はTelnetというものを用いてシェルで遠隔操作していましたが、Telnetで送受信するデータが平文という脆弱性がありました。

それに対する形で通信内容が暗号化される様になっているのがSSH。だからSecure な Shellと言われる。HttpにHttpsがついた様なニュアンス。

IPアドレス

ネットワーク通信を行うえで必要な、各ネットワーク機器を一意に区別する数字のこと。マイナンバーとか車のナンバーみたいなものです。IPを用いることで接続するサーバーを指定することができます。SSHでは接続先のIPを知る必要があります。

ユーザー

サーバー上で操作するための名前というか、操作者の名前です。ユーザーを複数作り権限を割り振ることでサーバー上の操作を制限することができます。個々の名前にしておけば、誰が何を実行したのかも分かります。SSHでは「どのユーザー(権限を持った人)で実行するか?」が大切になります。

linuxでは「root」という名前のユーザーが最初にいます。このrootは他人のパスワードも変えられるし、サーバー上全てのファイルを消すことなんて可能な、なんでもできる「スーパーユーザー」です。

グループ

ユーザーをくくる為の「組」のこと。そのままの意味です。同じグループ内であれば所有者が異なるファイルであっても操作ができます。(そのような権限が付与されている場合)

SSH認証方式

SSHはリモートでサーバーに接続しますが、サーバーからしてみれば「どこのよく分からないIP(あなたのPC)から自分をいじってもいいか?」と聞かれているので必ず認証をします。つまりこのサーバーをいじっても良い正規の人間かをチェックします。

その認証方式としてSSHでは主に

  • パスワード認証方式
  • 鍵交換方式

の2つがあります。

パスワード認証方式

接続する際のユーザー名と、そのユーザーに紐づいたパスワードで接続することができます。Webサービスでログインがあるものと同じですね。分かりやすいですが、接続の度にパスワードを求められてちょっと面倒です。

また総当たり攻撃で突破される可能性もあるので、運用とセキュリティ面では次の鍵交換がおすすめです。

鍵交換方式

秘密鍵と公開鍵というものを用いて認証を行います。鍵交換による認証原理の説明は今回は省きます。秘密鍵をクライアント(ローカル)において、公開鍵をサーバーにおいておきます。

ユーザーに紐づいた秘密鍵・公開鍵で認証を行います。秘密鍵は後述する通りにコマンドのオプションで指定できるので自動化やSSHの簡略化の際に便利になります。また秘密鍵のファイルが外部に漏れなければパスワード方式より安全です。

今回の解説では鍵交換方式でのSSH実行方法の設定も行います。

接続準備

今回は自分でVPSを借りて接続をするという状況として操作をします。ConohaやGMOではブラウザから最初にサーバーの設定を行います。

OSやrootユーザーのパスワードを設定してまず、サーバーが作られます。IPアドレスなども管理画面などに表示されていると思いますので控えておきます。

IPアドレスは「123.456.789.012」の様なピリオド4つで分けられた数字列のことです。

conhaの場合 xserverの場合

接続自体は簡単

IPアドレスとSSHユーザー名とパスワードがわかればあとは簡単です。とりあえず今回はVPSを借りているという想定なので、そのVPSのIPとrootユーザーパスワードがわかっているとします。

macならばターミナルを開きます。macにはsshを行うsshdが入っているので以下のコマンドを唱えます。

~ % ssh root@IP_ADRESS

ssh ユーザー名@IPアドレスを入力します。これは「指定したIPアドレスにrootというユーザー名でssh接続します!」という意味です。特にオプションを指定せず、パスワード認証方式が許可されている場合はパスワードを聞いてくるので入力します。

正しくパスワードを入力すると次の様な文章が出てきます。

The authenticity of host '*****************' can't be established.
RSA key fingerprint is *****************.
Are you sure you want to continue connecting (yes/no)? 
>yes #問題なければ

これはSSHキーフィンガースプリントと言われ日本語では「鍵指紋」と言われています。簡単に説明すると指定したIPで接続しても「本当に自分が繋ごうとしてるサーバーであっていますか?」と尋ねてくる。基本的にVPSなどは信頼できるのでyesを選択。

この時yesを押すとクライアント側にサーバーから送られた公開鍵のハッシュ が保存されます。次回以降の接続ではこの公開鍵のハッシュが一緒に認証に使用されます。なぜ一緒に使われるのかというと、サーバーのなりすまし防止です。

IPなどの情報に加えてさらにsshdサーバーを区別するためにこの情報を保存して、接続先を担保します。もし次回に保存した公開鍵とサーバーから提示された公開鍵ハッシュ が異なると以下の様な警告が出ます。

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!

接続の確認

認証が終えるとこれでssh完了です。意外と簡単ですよね。変わったかどうかを確かめるには、とりあえずターミナルの表示を確認してみてください。

Last login: Wed Jul 15 18:11:06 2020 from xxxxxxxxxxxxx
[root@HOST_NAME ~]$

この様にログイン時間、そして左側の表記が「ユーザー名@IPなどのホスト名 カレントディレクトリ名」になっています。この状態であればログインできています。

sshを止める場合には

[root@HOST_NAME ~]$ exit

と入力するとsshを終了(ログアウト)できます。

鍵交換の実装

前述した通りパスワード認証はわかりやすいですが、逐一パスワードを入力したりするのは面倒ですし、自動化ができません。流出や総当たりの危険性があるので出来たら鍵交換方式に変えた方がスムーズです。

  1. ここではrootでパスワード認証して初めてssh接続をした。
  2. このサーバーにはsshの公開鍵も秘密鍵もねえ!
  3. root用の鍵交換認証を実装

という状況で鍵交換を実装したいと思います。

秘密鍵と公開鍵を作成する

サーバーにログインした状態で秘密鍵と公開鍵を作成します。ユーザーのホーム ディレクトリには「.ssh」という隠しフォルダがあり、その中にssh用の鍵を格納します。

もしホームディレクトリに.sshディレクトリがない場合は作成します。今回は無かったとしましょう。

[root@HOST_NAME ~]$ mkdir .ssh
[root@HOST_NAME ~]$ chmod 700 ~/.ssh 

.sshディレクトリは権限を700にします。でないと鍵による接続ができません。その.sshに移動して以下のコマンドを唱えて両鍵を作成します。今回はパスフレーズ(追加のパスワード)はなしとします。パスフレーズを入れるとパスワード認証の様に逐一入力を求められてしまいます。

[root@HOST_NAME .ssh]$ ssh-keygen -t rsa -f id_rsa #-fはファイル名を指定できる。
Enter passphrase (empty for no passphrase): #←パスフレーズを入力。基本なしでもOK、その際はEnterをおす
Enter same passphrase again: #←パスフレーズを再入力。基本なしの時はEnterをおす
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx root@xxxxx
The key's randomart image is:
+--[ RSA 2048]----+
|                 |
|       .         |
|        o        |
|oo     . .       |
|*.. .   S .      |
|+E o       .     |
|=.o . .   .      |
|.+ . o ...       |
|*+.   ..+o       |
+-----------------+
[root@HOST_NAME .ssh]$ ls
[root@HOST_NAME .ssh]$ id_rsa id_rsa.pub

鍵を作成してディレクトリ内をみると2つのファイルが見つかります。pubがついている方が公開鍵で、もう片方が秘密鍵です。次に公開鍵をサーバーに登録し、600権限を割り振ります。以下のコマンドを唱えます。

[root@HOST_NAME .ssh]$ cat id_rsa.pub >> authorized_keys
[root@HOST_NAME .ssh]$ chmod 600 authorized_keys
[root@HOST_NAME .ssh]$ rm -fv id_rsa.pub #id_rsa.pubは捨てる

権限の設定を忘れて接続ができないミスが多いので注意。

秘密鍵をクライアント(自分のPC)へ送信

では次に接続元となる自分のPCへサーバーで作成した秘密鍵id_rsaを送信します。.sshフォルダ以外の場所に移動して、クラアントツールでひっぱてもいいですが、せっかくなのでscpコマンドを用いてやってみましょう。

scpコマンドでリモートからコピーする

scpはGUIのソフトでの送受信の正体です。リモートからローカルへのファイルのコピーをします。ファイルをコピーするコマンドにcpがありますが、あれがネットワークを通じている物だと思ってください。

リモートからローカルへコピーする時はローカル側で以下のような入力をします。

jun@MacBook-Pro% scp <ユーザー名>@<IPアドレス>:<ファイルまでのパス> <ファイルを置くローカルのパス>

scpの後に1つ目に「コピー元のファイルまでのパス」、2つ目に「コピーしたファイルの置き場所」を入力します。注意して欲しいのはscpコマンドはサーバーにログインして唱えるのではないということです。

よくわからないと思うので、同じようにリモートからあるファイルを取得する操作をFileZillaで行うと以下のようにメッセージが表示されます。やっていることはscpと変わりません。

状態:     "/var/www/html" のディレクトリ リストの表示成功
状態:     xxx.xx.xxx.xxx に接続中...
状態:     Using username "sample". 
状態:     Connected to    xxx.xx.xxx.xxx
状態:     /var/www/html/index.php のダウンロードを開始しています
状態:     42 バイト (1 秒) のファイル転送に成功しました

ローカルからリモートへ接続してファイルを取得しているのがわかります。scpによるファイルの送受信は サーバーにログインして行うのではなくて 、ローカル側から接続先を指定してファイルの送受信を行います。今回の秘密鍵を持ってくる場合は以下のように打ちます。

jun@MacBook-Pro% scp root@IP_ADRESS:~/.ssh/id_rsa ~/

「~/」というのは「ホームディレクトリ」配下という意味です。「rootの ~/.ssh/id_rsaにあるファイル」を「ローカルのホームディレクトリ 」にコピーしろ!という命令です。

秘密鍵を適当な箇所に置いて、権限を付与

秘密鍵は接続の際にパスで参照できればどこに置いてもいいのですが、わかりやすいようにローカルの.sshディレクトリ配下に入れることにします。Macにはホームディレクトリに.sshというssh用の隠しフォルダがあります。以下はローカルでの作業です。

jun@MacBook-Pro % cd ~ #ホームディレクトリに移動
jun@MacBook-Pro ~ % mv id_rsa .ssh/ && cd .ssh
jun@MacBook-Pro .ssh % ls -a
config  id_rsa  known_hosts

jun@MacBook-Pro .ssh % chmod 600 id_rsa

ここでも秘密鍵は600権限を付与しておきます。ここも忘れてハマりやすいので注意。ssh接続先が多くなり、鍵が増えたら「keys」などの適当な鍵収納用のフォルダを作るといいです。

鍵交換で接続する

以上で鍵交換の実装は完了です。実務的な運用の場合はサーバーでパスワードログインを禁止するなどが必要ですが今回は省略します。ではローカルから鍵を使ってログインしましょう。

.ssh配下に鍵があるので、鍵のパスを指定しする様に以下の様に唱えます。

jun@MacBook-Pro ~ % ssh -i ~/.ssh/id_rsa root@IP_ADRESS

パスワード式の接続に「-i」オプションを指定すると、「鍵交換で接続」という意味になります。-iの後にはローカルに保存した秘密鍵までのパスを指定します。あとはユーザー名とIPアドレスを入力すれば完了です。

パス指定が面倒〜〜

鍵交換で実装を行うとパスワードを入力しなくていいので、メモをみたり自動化の際には便利です。しかしパスの指定が面倒という欠点がありますが、簡単に解決できます。エイリアスを設定してとても簡単に接続できる様になります。

早速設定してみましょう。.sshディレクトリに移動して「config」というファイルを編集します。なければ作成してください。

jun@MacBook-Pro ~ % cd ~/.ssh
jun@MacBook-Pro .ssh % vi config

このconfigファイルに以下の情報を登録します。

Host sshconnect #好きな名前
 HostName IP_ADRESS
 User root
 Port 22
 IdentityFile ~/.ssh/id_rsa

configファイルに上記の様に記述すると以下のコマンドを唱えるだけで、HostNameで指定したサーバーへsshができます。

jun@MacBook-Pro ~ % ssh sshconnect

とっても短くになりました。「sshconnect」と入力しただけです。さらに鍵交換式なのでパスワードの入力も入りません。ちなみにユーザー名だけだと、パスワードが求められ入力しないといけません。セキュリティの関係上configファイルにはパスワードを記録できません。(FileZillaなどのソフトはソフト自身が記憶している)

完全にストレスフリーにHostのエイリアスを打つだけで接続するには鍵交換式しかできません。

scpでファイルを送ってみよう

scpファイルの送受信をまとめておきます。

エイリアスを用いた送受信

jun@MacBook-Pro ~ % scp ~/test.txt sshconnect:~/

sshの接続先は上記の様にエイリアス化するとリモート先をこんなに簡単に接続できます。エイリアスを使わない場合は以下の様に唱えます。

jun@MacBook-Pro ~ % scp -i ~/.ssh/id_rsa ~/test.txt root@IP_ADRESS:~/

以下はエイリアスを用いた鍵交換となっています。

ローカル→リモート

jun@MacBook-Pro ~ % scp ~/test.txt sshconnect:~/

# scp <ローカルのファイルまでのパス> <エイリアス>:<リモートのコピー先のパス>

リモート→ローカル

jun@MacBook-Pro ~ % scp sshconnect:~/test.txt ~/ 

# scp <エイリアス>:<リモートのファイルまでのパス> <ローカルのコピー先のパス>

ディレクトリ ごと移動(ローカルから)

膨大なファイルを輸送する時に早くて便利です。

jun@MacBook-Pro ~ % scp -r ~/heavy/ sshconnect:~/

-rを指定しないと「送信するものが普通のファイルじゃないよ!(not a regular file)」と怒られます。再起的にコピーされるので、ディレクトリ配下全てがコピーされます。

リモートからリモート

リモートサーバーその1をsshconnect01、その2をsshconnect02として01から02へ移動する場合です。ローカルを経由する方法と01で02に対するscpを行う方法があります。図示すると以下の様な感じです。

ローカル経由

  |-------sshconnect01
  |↓   ←
local
  |↓  →
  |------sshconnect02

リモートから直接
  |-------sshconnect01
  |↑   →       |↓
local          |↓
               |↓
          sshconnect02

リモートで直接

リモート01から02に直接送る場合はローカルで以下の様に打ちます

リモート01から02に直接送る場合はローカルで以下の様に打ちます

ディレクトリを写す場合は -r オプションを付けます。ただし、この方法は01は02への接続情報を持っていなければなりません。エリアスの場合も01の.ssh/configに sshconnect02についての記述を書く必要があります。02が鍵認証を行っている場合は01に02の鍵をおいておく必要があります。

ローカル経由

01から02に接続できない場合はローカルを経由する様にします。以下の様に打ちます。

jun@MacBook-Pro ~ % scp -3 sshconnect01:~/test.txt sshconnect02:~/ 

-3 オプションを使用します。ディレクトリコピーならばさらに -r を付けましょう。01からローカルに引っ張ってきてから、02へ送信します。自身の転送量は多くなりますが手軽にできます。

あとがき

以上がsshによるリモートログインとscpによるファイル送受信方法です。いつもはGUIソフトで操作しつつ、大量のファイル移動や権限が伴う移動などはコマンドを用いた方が便利です。まずはtest.txtなど影響のないファイルを作って、練習するといいでしょう。

Copyright © 2021 jun. All rights reserved.