ラズパイとWindowsでリンクローカルアドレスFTP（１）SSL無し

## この記事について

図のようにリンクローカルアドレス内で ラズパイ <-> WindowsPC等でのFTP通信するための環境を検証しました。  

<img width= 550 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/4e621ca8-cce2-3732-0d51-1c7c938aaf49.png>

クライアントからput/getするに際してサーバーがSSLに対応してない場合が有り得るのでSSL無し/有りについて２回に分けて記事を書きます。  

第一回目はSSL無しの接続手順を説明します。  

## 環境

### FTPクライアント

* Raspberry Pi 4 Model B Rev 1.2 / Raspberry Pi OS Lite 64-bit (Debian GNU/Linux 11 (bullseye))  
* static ip ： 192.168.1.100  
* local-link static ip ： 169.254.100.101  

### FTPサーバー

* DesktopPC　(Windows11 Pro 23H2)  
 
## FTPクライアント構築  

ラズパイにftpクライアントとiptables-persistentをインストールします。  

### パッケージインストール

```sh
#アップデート
sudo apt update  
sudo apt -y upgrade  

#python関連インストール
sudo apt install -y python3-dev python3-pip 　

#ftpとiptablesインストール
sudo apt install -y ftp iptables iptables-persistent

sudo apt update  
sudo reboot
```

### filer設定  

リンクローカルアドレス外とFTP通信させたくないのでfilter設定します。  

```sh: 初期化
sudo iptables -F
sudo iptables -X
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT
```

```sh: INPUT
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -d 127.0.0.0/8 ! -i lo -j REJECT --reject-with icmp-port-unreachable
sudo iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A INPUT -s 192.168.1.1/32 -p udp -m udp --dport 123 -j ACCEPT
sudo iptables -A INPUT -s 169.254.0.0/16 -p udp -m udp --dport 53 -j ACCEPT
sudo iptables -A INPUT -s 169.254.0.0/16 -p udp -m udp --dport 5353 -j ACCEPT
sudo iptables -A INPUT -s 169.254.0.0/16 -p tcp -m tcp --dport 20 -j ACCEPT
sudo iptables -A INPUT -s 169.254.0.0/16 -p tcp -m tcp --dport 21 -j ACCEPT
sudo iptables -A INPUT -s 169.254.0.0/16 -p tcp -m tcp --dport 2000:65535 -j ACCEPT
sudo iptables -A INPUT -s 192.168.1.0/24 -p tcp -m state --state NEW -m tcp --dport 22 --tcp-flags FIN,SYN,RST,ACK SYN -m hashlimit --hashlimit-upto 1/min --hashlimit-burst 10 --hashlimit-mode srcip --hashlimit-name t_sshd --hashlimit-htable-expire 120000 -j ACCEPT
sudo iptables -A INPUT -s 169.254.0.0/16 -p tcp -m state --state NEW -m tcp --dport 22 --tcp-flags FIN,SYN,RST,ACK SYN -m hashlimit --hashlimit-upto 1/min --hashlimit-burst 10 --hashlimit-mode srcip --hashlimit-name t_sshd --hashlimit-htable-expire 120000 -j ACCEPT
sudo iptables -A INPUT -s 192.168.1.0/24 -p icmp -m icmp --icmp-type 8 -j ACCEPT
sudo iptables -A INPUT -s 169.254.0.0/16 -p icmp -m icmp --icmp-type 8 -j ACCEPT
sudo iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7
sudo iptables -A INPUT -j REJECT --reject-with icmp-port-unreachable
```

### filter反映

```sh
sudo service netfilter-persistent reload
sudo service netfilter-persistent save
sudo sh -c "iptables-save >/etc/iptables.ipv4.filter"  
```

## FTPサーバー構築  

WindowsPCにFTPサーバーを立てます。  

### FTPサーバー有効化  

「Windows の機能の有効化または無効化」を検索してコントロールパネルを表示します。  

<img width= 650 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/dea82459-c6bd-7a4c-ac69-33e0b32c7aa6.png>  

<br/>

FTP Serverと管理コンソールを有効にします。   

<img width= 650 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/1a8381d4-7cdc-a9d4-831f-6637c4bf3c9b.png>  

<img width= 450 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/8fee6bbe-138b-f01e-ba20-abf8f0d2e59a.png>

有効化されたらIISマネージャーを表示します。  

<img width= 650 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/1f8df444-c309-a007-d8bc-1c9b117a3696.png>

### FTPサイトの追加  

IISマネージャーからFTPサイトを追加します。  

<img width= 650 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/5daf2b72-f33d-d7fd-669f-3d9ef354bebd.png>

WindowsPCにホストするFTPサーバーのサイト名と使用するdirectory名を設定します。  

<img width= 650 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/3c04dc88-92eb-a586-90ae-ef199be728d5.png>

SSL無しを選択して次に進みます。  

<img width= 650 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/d104c60a-5be8-b045-2ac2-b168b33956fe.png>

認証は基本を選択し指定されたユーザーとしてWindowsに普段ログインするユーザーを指定します。  

アクセス権は読み書き両方つけます。  

<img width= 650 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/0afac830-f90e-68f5-8124-422e74171d93.png>

## 動作確認  

クライアント(ラズパイ)のサンプルファイルをサーバー(WindowsPC)に転送し、サーバー上でrenameしてクライアントで取得します。  


### サンプルファイル作成  

サーバーに転送するサンプルファイル:test.txtを作成します。  

``` sh
user@MyPi:~ $ echo "Hello FTP!" | tee test.txt
user@MyPi:~ $ ls
test.txt
```


### クライアントからサーバーにログイン  

WindowsPCのリンクローカルアドレスを確認します。  

```
PS C:\Users\win-user> ipconfig

Windows IP 構成

イーサネット アダプター vEthernet (Default Switch):

   接続固有の DNS サフィックス . . . . .:
   リンクローカル IPv6 アドレス. . . . .: fe80::9730:e8dc:99f2:3a05%21
   自動構成 IPv4 アドレス. . . . . . . .: 169.254.191.227
   サブネット マスク . . . . . . . . . .: 255.255.0.0
```

ラズパイから169.254.191.227のFTPサーバーに接続します。  

```sh
user@MyPi:~ $ ftp
ftp> open 169.254.191.227
Connected to 169.254.191.227.
220 Microsoft FTP Service
```

サーバーのuserとログインパスワードを入力してサーバーにログインします。  

```sh
Name (169.254.191.227:user): win-user
331 Password required
Password: Windowsのログインパスワード
230 User logged in.
Remote system type is Windows_NT.
ftp>
```

### クライアントからサーバーにFTP転送  

最初はサーバー上にファイルが存在しません。

```sh
ftp> ls
200 PORT command successful.
125 Data connection already open; Transfer starting.
226 Transfer complete.
```

サーバーにtest.txtをputします。  

```sh
ftp> put test.txt
local: test.txt remote: test.txt
200 PORT command successful.
125 Data connection already open; Transfer starting.
226 Transfer complete.
12 bytes sent in 0.00 secs (239.1582 kB/s)
ftp>
```

test.txtがサーバー上にあることを確認します。  

```sh
ftp> ls
200 PORT command successful.
125 Data connection already open; Transfer starting.
11-26-23  12:12AM                   12 test.txt
226 Transfer complete.
ftp>
```

### サーバーからクライアントにFTP転送  

先ほど転送したtest.txtのファイル名を変更します。  

```sh
ftp> rename test.txt win-test.txt
350 Requested file action pending further information.
250 RNTO command successful.
ftp> ls
200 PORT command successful.
125 Data connection already open; Transfer starting.
11-26-23  12:12AM                   12 win-test.txt
226 Transfer complete.
ftp>
```

クライアントからサーバー上のwin-test.txtをgetします。  

```sh
ftp> get win-test.txt
local: win-test.txt remote: win-test.txt
200 PORT command successful.
125 Data connection already open; Transfer starting.
226 Transfer complete.
12 bytes received in 0.00 secs (28.7224 kB/s)
ftp>
```

ftpから抜けてuser directoryにwin-test.txtが存在することを確認します。  

```sh
ftp> exit
221 Goodbye.
user@MyPi:~ $ ls
test.txt  win-test.txt
```

WindowsPC上のFTPサーバーに対してラズパイ上のFTPクライアントからput/getできることが確認できました。  

個人的に、SSL無有に関わらずインターネットに接続した環境でFTPを使う気にならないですが、特にSSL無しのFTP通信をすることはお勧めしません念のため。  


## 参考文献  

* [Windowsのコマンド](https://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/ftp)
* [windows10にftpサービス導入でラズパイからwindowsへファイル転送が可能になる](https://www.mizutan.com/wordpress/?p=11217)