[lv4] ft_services (5/6) ftps実装

<- 前(4/6): wordpress実装
-> 次(6/6): grafana実装


9. ftps作る
(10. ftpsを永続ボリューム化)
11. grafanaの起動
12. influxdb -> grafana連携
13. telegraf -> influxDB連携
14. grafanaカスタマイズ

Q. ftpsとは?
A. File Transfer Protocol over SSL/TLSなるもの。
暗号化したファイルをサーバに転送するプロトコルです。送信側が暗号化し、受け取った側が復元しています。

Q. ゴールは?
A. FTPSサーバを立て、VMローカルにある適当なファイルをサーバに送ったり、そのファイルをローカルに戻せたりしたらよさそうです。

FTPSサーバを立てます。

後半戦に必要なツールを、まとめてインストールします。

/srcs/basecamp/Dockerfile

------------apk add install群を追加----------
RUN set -ex; \
	apk update; \
	apk add nginx openssl wget curl; \
	mkdir -p /run/nginx; \
# php-mysql (no such package): alpineに入らない
	apk add mysql mysql-client; \
	apk add php7-phar php7-fpm php7-common php7-session php7-iconv php7-json php7-gd php7-curl php7-xml php7-mysqli php7-imap php7-cgi fcgi php7-pdo php7-pdo_mysql php7-soap php7-xmlrpc php7-posix php7-mcrypt php7-gettext php7-ldap php7-ctype php7-dom; \
# php7-pharはwp-cliで必須
# openrc: rc-service   mandoc+man-pages: man
	apk add openrc mandoc man-pages; \
	apk add vsftpd; \
	# grafana-server
	apk add libc6-compat; \
	apk add influxdb telegraf
------------apk add install群 ここまで-------


------------wget 群追加------------------
# wget 追加
# grafana
# ref: https://zenn.dev/tkomatsu/scraps/42e6cd3f96f4e5
RUN set -ex; \
	wget https://dl.grafana.com/oss/release/grafana-7.4.5.linux-amd64.tar.gz; \
	tar -zxvf grafana-7.4.5.linux-amd64.tar.gz; \
	rm grafana-7.4.5.linux-amd64.tar.gz; \
	mv grafana-7.4.5 grafana; \
	mv grafana/ /
------------wget 群ここまで------------------


nginx.yamlをコピーして設定を変更させます。

/srcs/ftps/ftps.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: ftps
 name: ftps
spec:  # podの概要
 replicas: 1
 selector:
   matchLabels:
     app: ftps
 template:
   metadata:
     labels:
       app: ftps
   spec:
     containers:
     - image: myftps
       imagePullPolicy: Never
       name: ftps
       ports:
       - containerPort: 20
         name: ftps-datapath
       - containerPort: 21
         name: ftps
       - containerPort: 60000
---
apiVersion: v1
kind: Service
metadata:
 name: ftps
 annotations:
   metallb.universe.tf/allow-shared-ip: "ft_services"
spec:
 type: LoadBalancer
 selector: # DeploymentのPodのlabelとセット
   app: ftps
 ports:
   - name: ftps-datapath
     port: 20
   - name: ftps
     port: 21
   - name: pasv
     port: 60000

Q. port 20, 21, 60000?
A. port 21はやり取りの開始と終了の制御だけ、です。データの送受信に使われるのがport 20なので、どちらも開けます。
60000は、パッシブモード接続のために使用します。confの設定と合わせますが、port 30000以上でありさえすればよいとか。
portsが複数ある場合は- name 必須です。

(ref) FTPの仕組み!「 21番ポート」と「20番ポート」 「アクティブモード」と「パッシブモード」について
https://mechalog.com/ftp-shikumihttps://mechalog.com/ftp-shikumi

次、confファイルを仕上げます。

/srcs/ftps/vsftpd.conf

# listen=NOだとスーパーサーバから。YESでスタンドアロン
# ref: https://linuxjm.osdn.jp/html/vsftpd/man8/vsftpd.8.html
listen=YES

# ローカルユーザアカウント(/etc/passwd に記録されている ユーザ ID が 500 以降のユーザ アカウント)のログインを許可する。
local_enable=YES
# 次の許可。制御対象 FTP コマンド : STOR, DELE, RNFR, MKD, RMD, APPE, SITE
write_enable=YES

# サーバ側が使用するデータ転送用ポート番号の指定方法を定義する。 YES: ftp_data_port で指定するポートを使用する。
connect_from_port_20=YES
ftp_data_port=20

# seccomp filter をオフにする ( ログインに失敗する場合はオフにする )
# seccompはlinuxカーネルの3.5から入ったシステムコールのフィルター。
# カーネルのバージョンが3.5以上のときはONにしないといけないらしい。
seccomp_sandbox=NO

# FTPで特定のユーザに上位ディレクトリを見せないための設定
# ref: https://qiita.com/kenichiro-yamato/items/08aa845b61804373d739
anonymous_enable=NO
chroot_local_user=YES
allow_writeable_chroot=YES

chroot_list_enable=YES
chroot_list_file=/etc/vsftpd/chroot_list

# TLSを有効化
ssl_enable=YES

# 使用プロトコル (必要なプロトコルをYESに設定する)
ssl_sslv2=NO
ssl_sslv3=NO
ssl_tlsv1=YES
#ssl_tlsv1_1=NO この設定は存在しない
#ssl_tlsv1_2=YES

# 暗号化方式
# ssl_ciphers=kEECDH+AESGCM+AES128:kEECDH+AESGCM:kEECDH+AES128:kEECDH+AES:!aNULL:!eNULL:!LOW:!EXP

# サーバ証明書、秘密鍵
rsa_cert_file=/etc/nginx/ssl/ft_service.crt
rsa_private_key_file=/etc/nginx/ssl/ft_service.key

# パッシブモードの接続を許可する
pasv_enable=YES

# FTPサーバのIPアドレスを指定(パッシブモードで接続時)
pasv_address=192.168.10.10
# ※上記のIPは固定となります。

# ポート指定 00: 1024~65535番のうちのポート番号がランダムで使用されるようになります。
pasv_min_port=60000
pasv_max_port=60000
# ※ポートはハイポートであれば特に指定はありません

pasv_addr_resolve=YES

# vsftpd および xferlog の両形式のログを取得する。
# ただし、xferlog_enable が YES でなければならない。
dual_log_enable=YES
xferlog_enable=YES

# FTP のすべての要求と応答を記録する。 デバッグ等に使用する。
# xferlog_std_format ディレクティブは NO に設定することが必須である。
log_ftp_protocol=YES
xferlog_std_format=NO

# メッセージ ファイル (message_file で指定) を設置したディレクトリにアクセスがあると、メッセージ ファイルの内容を表示する。
dirmessage_enable=YES

vsftpd_log_file=/var/log/vsftpd.log
xferlog_file=/var/log/vsftpd.log

Q. それぞれどういう意味?
A. 一覧表があります。
(ref) http://www.nina.jp/server/redhat/vsftpd/vsftpd.conf.html

Q. chroot_list_enable=YES ?
A.
実動作を先に案内します。
1. ftpsサーバには、利用ユーザを登録できます。
2. ローカルVMからftpsサーバにアクセスするときに、ユーザを指定してアクセスします。
3. ftpsサーバの中身を全員が全部見えてしまっては、実運用に問題があります。
4. そのため、ユーザごとにルートディレクトリを決められます。特定の階層以上に上がれないよう、制限を設けます。
5. chroot_list_file=/etc/vsftpd/chroot_list
とすることで、/etc/vsftpd/chroot_listに制限するユーザのリストを設置し、有効化できます。
6. chroot_listファイルの中身に、local_root=<path>を指定することで、ログイン時のパスを指定できます。

/srcs/ftps/chroot_list

local_root=/var/www/ftp_dir


Q. エラーログ?
A. 多分出ません。頑張ったのですがまだうまくいきません。
vsftpd_log_file=/var/log/vsftpd.log
xferlog_file=/var/log/vsftpd.log
ここに出ればいいのですが。

Q. どこいじる?
A. このあたりをそろえます。
・外部IP(192.168.10.10)
・passiveのport(60000)
・ssl認証キーのパス rsa_cert_file / rsa_private_key_file

Q. なぜこんなに多い?
A. 各種参考サイトを継ぎ足したため。最低限の設定を探す余地はあります。

次に、ftpsユーザの設定です

/srcs/ftps/Dockerfile

FROM basecamp

# -S 指定されたシェルの存在や妥当性を確認しません。
# -G -G groups 追加グループ。 このオプションは、ユーザに付与する追加グループを指定します。 ユーザは、ログイングループに加え、これらのグループのメンバです。
# -D パスワードの入力まちをスルー?

# chpasswd = username:password
RUN adduser -D ftp-user \
 && echo 'ftp-user:ftp-user' | chpasswd

# FTPで接続したときにデフォルトでたどり着くディレクトリ
RUN mkdir -p /var/www/ftp_dir &&\
	chown ftp-user /var/www/ftp_dir &&\
	chmod 755 /var/www/ftp_dir

RUN mkdir -p /etc/vsftpd/user_conf

RUN touch /var/log/vsftpd.log

COPY start.sh /tmp/start.sh
COPY vsftpd.conf /etc/vsftpd/vsftpd.conf
COPY chroot_list /etc/vsftpd/chroot_list

# 書き込み権限いるかも
RUN chmod -R 777 /tmp /var /etc

# port
EXPOSE 20 21 60000

WORKDIR /

CMD [ "/tmp/start.sh" ]

Q. adduser?
A. Alpineでは、useraddが使えません。パスワードの入力待機を避けるために、chpasswdでパスワードを設定します。

ftpsも、起動コマンド必要です

/srcs/ftps/start.sh

#!/bin/sh

/usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf

Q. .conf?
A. vsftpd <confのパス> で実行します。
設定ファイルの宣言を必須とするコマンドなので注意。

ここまで一息に書ききって、ようやく動作確認です。

/run.sh

# del
kubectl delete -f srcs/ftps/ftps.yaml

# image
docker build -t myftps srcs/ftps/.

# apply
kubectl apply -f srcs/ftps/ftps.yaml
➜  kubectl get svc
NAME            TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                                    AGE
ftps            LoadBalancer   10.110.1.107     192.168.10.10   20:35811/TCP,21:1316/TCP,60000:63997/TCP   79s
kubernetes      ClusterIP      10.96.0.1        <none>          443/TCP                                    17m
mysql           ClusterIP      None             <none>          3306/TCP                                   83s
nginx-metallb   LoadBalancer   10.106.43.97     192.168.10.10   80:12714/TCP,443:55763/TCP                 88s
phpmyadmin      LoadBalancer   10.102.204.165   192.168.10.10   5000:2054/TCP                              86s
wordpress       LoadBalancer   10.101.118.158   192.168.10.10   5050:49817/TCP                             81s

ftpsを見ると、LoadBalancerのport 20/21/60000が開いてます。

Q. 実動作
A. FTPSサーバとやりとりには、bashのようなコマンドツールが必要です。「lftp」なるツールが便利なので、VMローカルに落とします。

apt-get install lftp

sh ./run.sh
VMにて、
-> lftp -e 'set ssl:verify-certificate false' -u ftp-user -p 21 192.168.10.10
-> pass: ftp-user

でログイン。
IPやユーザー名が間違えていても、必ずlftpが起動します。
lftp ftp-user@192.168.10.10:/> pwd
ftp://ftp-user@192.168.10.10:21/

lftp内でコマンドが動作されれば開通です。

  _n
 ( l    _、_
  \ \ ( <_,` )
   ヽ___ ̄ ̄  )   グッジョブ!!
     /    /

続いてファイル転送できるか確認。

// ローカルVMにtext.txtを作成 ( ! : ローカルVM操作に切り替え )
!echo "aaaaa" > test.txt

// ftpsサーバにtest.txtを設置。
put test.txt

// ftpsサーバにファイルがコピーされていればOK

// ローカルVMで、test.txtを削除
!rm test.txt

// ftpsサーバからローカルVMに、test.txtをコピー
get test.txt

// ftpsサーバからローカルVMにファイルがコピーされていればOK

Q. 'set ssl:verify-certificate false'?
A. SSLの正当性を無視します。今回オレオレ証明書なので、必ずエラーが出てしまいます。必須です。また、エラーがSSL設定成功の確認になります。


・(10. ftpsを永続ボリューム化)
仕様ならそれでいいかもしれませんが。今はpodを消すと、ftpsサーバにうつしたデータが消失します。
ローカルフォルダをftpsサーバの保存領域にマウントすれば、データを残せます。

Q. ftpsサーバの保存領域?
A. /home/<user名>
chroot_listの中で、local_root=/var/www/ftp_dir としたはずですが、どうもftpsサーバ内でのログイン場所?保存場所にはならないようです。
ftpsサーバのマウントを/homeに設定します。

/srcs/ftps/ftps.yaml

        - containerPort: 60000
         name: pasv
--------------追加----------------
       volumeMounts:
       - name: ftps-persistent-storage
         mountPath: /home
     volumes:
     - name: ftps-persistent-storage
       persistentVolumeClaim:
         claimName: ftps-pv-claim
-------------ここまで----------------
---

pv.yamlをコピーして、名称だけ変更します。
/srcs/ftps/ftps-pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
 name: ftps-pv-volume
 labels:
   type: local
spec:
 storageClassName: manual
 capacity:
   storage: 100Mi
 accessModes:
   - ReadWriteOnce
 hostPath:
   path: "/data"
---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: ftps-pv-claim
spec:
 storageClassName: manual
 accessModes:
   - ReadWriteOnce
 resources:
   requests:
     storage: 100Mi

また、ローカルVMで以下の操作を行います。
Q. マウントされた場合、書き込み権限はどっちにあるの?
A. ローカルVMの権限が優先されるように見えます。
今のままだと、ローカル/data/ftp-userフォルダに書き込むことになりますが、権限ありません。

/run.sh

# ftps pv
if [ ! -d "/data/ftp-user" ]; then
 sudo mkdir -p /data/ftp-user
 sudo chmod 777 /data/ftp-user
 echo "[run.sh] /data/ftp-user made."
else
 echo "[run.sh] /data/ftp-user already exist."
fi

# lftp install
sudo apt-get install lftp

# apply
kubectl apply -f srcs/ftps/ftps-pv.yaml

sudo mkdir /data/ftp-user
sudo chmod 777 /data/ftp-user

ftpsサーバにtest.txtを設置し、ftpsのpodを再起動し、残っていたら大成功。

sh ./run.sh
lftp -e 'set ssl:verify-certificate false' -u ftp-user -p 21 192.168.10.10
<ファイル設置する>

sh ./run.sh # podを再起動。永続ボリュームでなければ消失しているはず。
lftp -e 'set ssl:verify-certificate false' -u ftp-user -p 21 192.168.10.10
ls

ある?



これで永続ボリューム化完了。


---TRUE END---


-> 次(6/6) :grafana実装

いいなと思ったら応援しよう!