ftplib.FTP_TLS.auth()
ftplib.FTP_TLS.auth()
メソッドは、この FTP_TLS
クラスのインスタンスで使用されるメソッドで、FTPコントロール接続をTLSで保護するための認証プロセスを開始します。
具体的には、以下のことを行います。
- AUTHコマンドの送信: クライアント(
FTP_TLS
インスタンス)はFTPサーバーに対してAUTH TLS
コマンドを送信します。これは、「TLSを使ってセキュアな接続を確立したい」という意思表示です。 - TLSハンドシェイクの開始: サーバーが
AUTH TLS
コマンドを受け入れると、クライアントとサーバー間でTLSハンドシェイクが開始されます。これは、暗号化された通信チャネルを確立するためのプロセスです。 - セキュアなコントロール接続の確立: TLSハンドシェイクが成功すると、FTPのコントロール接続(コマンドや応答がやり取りされるチャネル)がTLSによって暗号化され、安全な状態になります。
auth() メソッドの役割の重要性
通常のFTP接続では、ユーザー名やパスワードを含むすべての通信が平文で送信されるため、盗聴のリスクがあります。FTP_TLS
を使用し、auth()
メソッドを呼び出すことで、ログイン情報やその後のFTPコマンドが暗号化されるため、セキュリティが向上します。
注意点
FTP_TLS
のコンストラクタでホストを指定した場合、内部的にconnect()
が呼び出され、その後、ユーザー名とパスワードが指定されていればlogin()
も呼び出されます。login()
メソッドは、内部でauth()
を呼び出してTLS認証を試みます。したがって、通常は明示的にauth()
を呼び出す必要がない場合もありますが、特定のシナリオやデバッグ目的で使用することが考えられます。auth()
メソッドは、コントロール接続を保護するものであり、データ接続(ファイルの転送が行われるチャネル)を自動的に保護するものではありません。データ接続もTLSで保護したい場合は、auth()
の後にprot_p()
メソッドを呼び出す必要があります。prot_p()
は、FTPサーバーに対してPROT P
コマンドを送信し、データ接続もプライベート(保護された)モードにするよう要求します。
from ftplib import FTP_TLS
try:
# FTP_TLS オブジェクトを作成
# デフォルトでは、ポート21(FTPの標準ポート)に接続し、
# 接続後に暗黙的にAUTH TLSコマンドが送信され、TLSハンドシェイクが試みられる
ftp = FTP_TLS('your_ftp_server.com')
# デバッグレベルを設定すると、通信の詳細を見ることができる
# ftp.set_debuglevel(2)
# 接続後、ログイン(ここで内部的にauth()が呼び出されることが多い)
ftp.login('your_username', 'your_password')
# データ接続もTLSで保護する場合は、prot_p()を呼び出す
ftp.prot_p()
# ファイルリストを取得
ftp.dir()
# 接続を閉じる
ftp.quit()
except Exception as e:
print(f"エラーが発生しました: {e}")
FTP_TLS.auth()
は、内部的に AUTH TLS
コマンドをサーバーに送信し、TLSハンドシェイクを開始する役割を担います。このプロセス中に問題が発生すると、様々なエラーに繋がります。
ftplib.error_perm: 504 Security mechanism 'TLS' not implemented. (または類似の5xxエラー)
- トラブルシューティング
- サーバーのFTPSサポートの確認
まず、接続しようとしているFTPサーバーがFTPSをサポートしていることを確認してください。可能であれば、FileZillaなどのGUIクライアントでFTPS接続を試み、成功するかどうか確認します。 - FTPSモードの確認 (Explicit vs. Implicit)
ftplib.FTP_TLS
は明示的なFTPS (FTPES) を想定しています。これは、通常のFTPポート (通常21番) で接続を開始し、その後AUTH TLS
コマンドでTLSを有効にする方式です。- もしサーバーが暗黙的なFTPS (通常ポート990) のみをサポートしている場合、
FTP_TLS
クラスでは直接接続できません。その場合は、ssl.wrap_socket
を使用してソケットを手動でラップするなどの工夫が必要になることがあります。ただし、Pythonの新しいバージョンではFTP_TLS
の内部実装が改善され、暗黙的なFTPSも扱いやすくなっている場合がありますので、まずは明示的FTPSとして試してみてください。
- SSL/TLSバージョンの指定
サーバーが特定のTLSバージョンを要求している場合、Pythonコードでそれを明示的に指定できる場合があります。import ssl from ftplib import FTP_TLS ftp = FTP_TLS('your_ftp_server.com') # 必要に応じてTLSバージョンを指定 # ftp.ssl_version = ssl.PROTOCOL_TLSv1_2 # 例: TLSv1.2を明示的に指定 # ftp.ssl_version = ssl.PROTOCOL_TLS # 最適なバージョンを自動選択(推奨) ftp.login('username', 'password')
- ファイアウォールの確認
クライアント側、サーバー側の両方のファイアウォールが、FTPS通信に必要なポート (通常21番) およびデータ接続用のポート (PASVモードの場合、サーバーがランダムに開くポート範囲) を許可しているか確認します。
- サーバーのFTPSサポートの確認
- 原因
- FTPサーバーがTLS/SSLをサポートしていない。
- FTPサーバーが明示的なFTPS (FTPES) をサポートしていない。一部のサーバーは暗黙的なFTPS (FTPSポート990) のみをサポートし、通常のFTPポート (21) で
AUTH TLS
コマンドを受け付けない場合があります。 - FTPサーバーがTLSの特定のバージョン (例: TLSv1.2、TLSv1.3) を要求しているが、クライアントがそれに対応していないか、または設定が合致していない。
- ファイアウォールが
AUTH TLS
コマンドやTLSハンドシェイクをブロックしている。
ftplib.error_perm: 530 Login authentication failed. (または類似の5xxエラー)
- 原因
- ユーザー名またはパスワードが間違っている。
- サーバーが匿名ログインを許可していない、または特定のIPアドレスからの接続を制限している。
- サーバー側のユーザーアカウントに問題がある(ロックアウト、有効期限切れなど)。
- 稀に、
FTP_TLS
の初期のバージョンで、コンストラクタでユーザー名とパスワードを渡すとlogin()
が内部でauth()
を呼び出す前に認証を試み、エラーになることが報告されていましたが、これは現在のPythonバージョンではほとんど解消されています。
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed
- トラブルシューティング
- 信頼できる証明書の使用
理想的には、信頼できるCAによって署名された証明書を使用しているFTPサーバーに接続することをお勧めします。 - 自己署名証明書への対応 (非推奨だが緊急時)
開発環境やテスト環境などで自己署名証明書を使用している場合、セキュリティリスクを理解した上で、検証を無効にすることができます。
警告:import ssl from ftplib import FTP_TLS # SSLコンテキストを作成し、証明書検証を無効にする(非推奨!) context = ssl.create_default_context() context.check_hostname = False context.verify_mode = ssl.CERT_NONE ftp = FTP_TLS('your_ftp_server.com', context=context) ftp.login('username', 'password')
context.verify_mode = ssl.CERT_NONE
は中間者攻撃 (Man-in-the-Middle attack) のリスクを高めるため、本番環境での使用は絶対に避けるべきです。 - CA証明書の指定
サーバーの証明書を発行したCAの証明書 (.pem
ファイルなど) がある場合、それを明示的に指定することができます。import ssl from ftplib import FTP_TLS context = ssl.create_default_context(cafile="/path/to/your/ca_bundle.pem") ftp = FTP_TLS('your_ftp_server.com', context=context) ftp.login('username', 'password')
- ホスト名の確認
接続先のホスト名が、証明書に記載されているCN (Common Name) またはSAN (Subject Alternative Name) と一致していることを確認します。IPアドレスで接続している場合、証明書がIPアドレスをカバーしていないとこのエラーが出ることがあります。
- 信頼できる証明書の使用
- 原因
- サーバーのSSL/TLS証明書が信頼されていない(自己署名証明書、期限切れ、発行元が不明など)。
- クライアント側のシステムに適切な信頼された証明書ストア (CA証明書) がない。
- サーバーのホスト名と証明書に記載されているホスト名が一致しない。
TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond (Windowsの場合) または socket.timeout: timed out
- トラブルシューティング
- サーバーの稼働状況の確認
サーバーがオンラインであり、FTPサービスが稼働しているか確認します。 - ネットワーク接続の確認
ping
コマンドなどでサーバーに到達できるか確認します。 - タイムアウト値の調整
FTP_TLS
コンストラクタでタイムアウト値を増やしてみます。from ftplib import FTP_TLS ftp = FTP_TLS('your_ftp_server.com', timeout=30) # 30秒に設定 ftp.login('username', 'password')
- ファイアウォールの確認
前述の通り、必要なポートがブロックされていないか確認します。
- サーバーの稼働状況の確認
- 原因
- FTPサーバーがダウンしているか、到達不可能である。
- ネットワークの問題(ファイアウォール、ルーティングなど)。
- サーバーがビジーで、TLSハンドシェイクの応答に時間がかかっている。
- トラブルシューティング
- デバッグレベルの上げ
ftp.set_debuglevel(2)
を設定して、FTPの制御接続で送受信されるコマンドと応答を詳細に確認します。これにより、どの段階でエラーが発生しているか特定しやすくなります。from ftplib import FTP_TLS ftp = FTP_TLS('your_ftp_server.com', 'username', 'password') ftp.set_debuglevel(2) # デバッグ出力を最大にする ftp.login('username', 'password') # ... その後の操作
- Wiresharkなどのパケットキャプチャツール
より詳細な調査が必要な場合、Wiresharkなどのネットワークプロトコルアナライザを使用して、FTPS接続のパケットをキャプチャし、TLSハンドシェイクの段階で何が起きているかを確認します。これにより、クライアントとサーバー間の実際の通信内容が明らかになり、問題の特定に非常に役立ちます。 - Pythonバージョン
Pythonのバージョンによっては、ftplib
の挙動やSSLモジュールに修正が入っていることがあります。最新の安定版Pythonにアップグレードすることで問題が解決する場合もあります。 - サーバー側の設定
サーバー側のFTPS設定(例えば、特定のTLSバージョン、暗号スイート、データ接続のモードなど)が厳しすぎたり、一般的なクライアントでは扱いにくい設定になっている可能性があります。可能であれば、サーバー管理者に問い合わせて設定を見直してもらうことを検討します。
- デバッグレベルの上げ
- 原因
- オペレーティングシステムレベルのソケットエラー。
- サーバーがTLSハンドシェイクを途中で切断した。
- Pythonの
ftplib
ライブラリ自体のバグ(稀)。
- 公式ドキュメントやStack Overflowを参照
ftplib
の公式ドキュメントや、Stack Overflowなどの開発者コミュニティで同様の問題が報告されていないか検索してみることも有効です。 - 他のFTPSクライアントで試す
FileZillaなどの信頼性の高いFTPSクライアントを使用して、同じサーバー、ユーザー名、パスワードで接続を試み、成功するかどうか確認します。もしGUIクライアントで成功するなら、Pythonコードの問題である可能性が高いです。 - ステップバイステップで確認
接続、認証、データ転送といった各ステップで問題がないか、一つずつ確認していきます。 - エラーメッセージをよく読む
Pythonが返すエラーメッセージは、問題の原因を特定するための最も重要な情報源です。特にftplib.error_perm
やssl.SSLError
の後に続く詳細メッセージやFTP応答コード (5xxなど) に注目してください。
ftplib.FTP_TLS.auth()
メソッドは、Pythonの ftplib
モジュールを使ってFTPS (FTP over TLS/SSL) 接続を確立する際に、コントロール接続をTLSで保護するための認証プロセスを開始します。
しかし、実際のプログラミングでは、FTP_TLS
クラスのインスタンスを作成し、login()
メソッドを呼び出す際に、内部的に auth()
が自動的に呼び出されることがほとんどです。そのため、auth()
メソッドを直接明示的に呼び出すコード例は稀です。
これは最も一般的な FTP_TLS
の使い方です。ユーザー名とパスワードを login()
メソッドに渡すと、Pythonの ftplib
が自動的に AUTH TLS
コマンドを送信し、TLSハンドシェイクを処理してくれます。
from ftplib import FTP_TLS
import ssl # SSL/TLS関連のオプション設定に使用
FTP_SERVER = 'your_ftp_server.com' # 接続先のFTPサーバーのホスト名またはIPアドレス
USERNAME = 'your_username' # FTPユーザー名
PASSWORD = 'your_password' # FTPパスワード
try:
# 1. FTP_TLS オブジェクトの作成
# タイムアウトを設定することも推奨されます
ftp = FTP_TLS(FTP_SERVER, timeout=30)
# (オプション) デバッグレベルを設定すると、内部のFTPコマンド/応答が見れる
# ftp.set_debuglevel(2)
# 2. ログイン
# ここで内部的に 'AUTH TLS' コマンドが送信され、
# TLSハンドシェイクが実行されます。
# 認証が成功すると、コントロール接続が暗号化されます。
ftp.login(USERNAME, PASSWORD)
print("ログイン成功。コントロール接続がTLSで保護されました。")
# 3. データ接続の保護 (PROT P コマンドの送信)
# ファイル転送などのデータ接続もTLSで保護する場合に呼び出す
ftp.prot_p()
print("データ接続もTLSで保護されます。")
# 4. FTP操作の実行 (例: ファイルリストの取得)
print("\nサーバー上のファイルとディレクトリ:")
files = []
ftp.dir(files.append) # ディレクトリリストを取得し、リストに追加
for line in files:
print(line)
# 5. 接続の終了
ftp.quit()
print("\nFTP接続が正常に終了しました。")
except Exception as e:
print(f"エラーが発生しました: {e}")
コードの解説:
ftp.prot_p()
: これはAUTH TLS
とは異なり、データ接続(ファイルの送受信)もTLSで保護するための重要なステップです。これを呼び出さない場合、コントロール接続は暗号化されても、ファイルの送受信は平文で行われる可能性があります。ftp.login(USERNAME, PASSWORD)
: このメソッドが呼び出されると、ftplib
は以下の処理を自動的に行います。- FTPサーバーに
AUTH TLS
コマンドを送信します。 - サーバーが応答すると、クライアントとサーバー間でTLSハンドシェイクが実行され、コントロール接続が暗号化されます。
- その後、暗号化されたチャネルを通じてユーザー名とパスワードを送信し、認証を試みます。
- FTPサーバーに
ftp = FTP_TLS(FTP_SERVER, timeout=30)
:FTP_TLS
クラスのインスタンスを作成し、FTPサーバーへの接続を開始します。この時点ではまだTLSは有効になっていません。
FTP_TLS.auth()
を直接呼び出すユースケースは非常に稀ですが、例えば login()
の前にTLS認証が成功したことを確認したい場合や、カスタムな認証フローを実装したい場合などが考えられます。
**しかし、これは通常の ftplib
の使用方法から逸脱しており、予期しない挙動やエラーを引き起こす可能性があるため、**特別な理由がない限り推奨されません。
以下に、無理やり auth()
を呼び出す場合の概念的な例を示しますが、このコードは通常のFTPS接続では不要であり、デバッグ目的以外での使用は推奨されません。
from ftplib import FTP_TLS
import ssl
FTP_SERVER = 'your_ftp_server.com'
USERNAME = 'your_username'
PASSWORD = 'your_password'
try:
ftp = FTP_TLS(FTP_SERVER, timeout=30)
ftp.set_debuglevel(2) # デバッグ出力を有効にして、auth()の挙動を確認
# 接続は行うが、まだログインはしない
ftp.connect(FTP_SERVER)
print(f"サーバー {FTP_SERVER} に接続しました。")
# ここで明示的に auth() を呼び出す (通常はlogin()が自動的に行う)
# これにより、コントロール接続がTLSで保護されます
ftp.auth()
print("コントロール接続でTLS認証が開始され、確立されました。")
# TLSが確立された安全な接続上でログイン情報を送信
ftp.login(USERNAME, PASSWORD)
print("ログイン成功。")
ftp.prot_p()
print("データ接続も保護されます。")
ftp.dir()
ftp.quit()
print("FTP接続が正常に終了しました。")
except Exception as e:
print(f"エラーが発生しました: {e}")
なぜ auth()
を直接呼び出すのが稀なのか:
ftplib.FTP_TLS
クラスは、インスタンスが作成された時点、または login()
メソッドが呼び出された時点で、自動的に AUTH TLS
コマンドを送信し、必要なTLSハンドシェイクを行います。これにより、開発者は複雑なセキュリティ設定を意識することなく、安全なFTPS接続を確立できます。
もし auth()
を直接呼び出そうとして、FTP_TLS
の内部状態と食い違いが生じた場合、error_perm
や ssl.SSLError
などのエラーが発生する可能性があります。
ftplib.FTP_TLS.auth()
はFTPS接続の内部的なメカニズムであり、通常は開発者が直接呼び出す必要はありません。 FTP_TLS
オブジェクトを作成し、login()
メソッドを呼び出すだけで、自動的にTLSによるコントロール接続の保護が行われます。
しかし、「`ftplib.FTP_TLS.auth()`` に関連するプログラミングの代替方法」という文脈で考えられるのは、以下の2つの方向性です。
ftplib.FTP_TLS
クラスの通常の利用方法(auth()
を意識しない方法): これが最も一般的で推奨される方法です。ftplib
を使用しない、より低レベルなソケットプログラミングによる FTPS 接続: これは非常に複雑ですが、ftplib
の抽象化された挙動に満足できない場合や、特殊な FTPS プロトコル要件がある場合に検討される可能性があります。
ftplib.FTP_TLS クラスの通常の利用方法 (推奨)
これは auth()
を明示的に呼び出さないにも関わらず、その機能(コントロール接続の TLS 保護)を自動的に利用する方法です。これが事実上の「代替方法」であり、最も実用的です。
特徴
- SSL/TLS コンテキストのカスタマイズを通じて、証明書検証の挙動などを制御できる。
- 内部で
AUTH TLS
コマンドの送信、TLS ハンドシェイク、そしてログイン処理が自動的に行われる。 ftplib
が提供する高レベルな抽象化を利用するため、コードが簡潔で分かりやすい。
コード例 (再掲)
from ftplib import FTP_TLS
import ssl # SSL/TLS 関連のオプション設定に使用
FTP_SERVER = 'your_ftp_server.com' # 接続先のFTPサーバーのホスト名またはIPアドレス
USERNAME = 'your_username' # FTPユーザー名
PASSWORD = 'your_password' # FTPパスワード
try:
# FTP_TLS オブジェクトの作成
# タイムアウトを設定することも推奨されます
ftp = FTP_TLS(FTP_SERVER, timeout=30)
# (オプション) SSL コンテキストのカスタマイズ
# 例: 自己署名証明書を許可する場合 (非推奨!)
# context = ssl.create_default_context()
# context.check_hostname = False
# context.verify_mode = ssl.CERT_NONE
# ftp = FTP_TLS(FTP_SERVER, timeout=30, context=context)
# (オプション) デバッグレベルを設定すると、内部のFTPコマンド/応答が見れる
# ftp.set_debuglevel(2)
# ログイン (ここで内部的に 'AUTH TLS' コマンドが送信され、TLS ハンドシェイクが実行される)
ftp.login(USERNAME, PASSWORD)
print("ログイン成功。コントロール接続がTLSで保護されました。")
# データ接続もTLSで保護する場合 (PROT P コマンドの送信)
ftp.prot_p()
print("データ接続もTLSで保護されます。")
# FTP操作の実行
print("\nサーバー上のファイルとディレクトリ:")
files = []
ftp.dir(files.append)
for line in files:
print(line)
# 接続の終了
ftp.quit()
print("\nFTP接続が正常に終了しました。")
except Exception as e:
print(f"エラーが発生しました: {e}")
この方法が、Python で FTPS クライアントを実装する際の標準的なアプローチであり、auth()
メソッドの機能は透過的に提供されます。
これは ftplib
の抽象化を使用せず、Python の socket
モジュールと ssl
モジュールを直接組み合わせて FTPS 接続を構築する方法です。非常に複雑で、FTPS プロトコル (AUTH TLS
, PROT P
など) や SSL/TLS ハンドシェイクの詳細な知識が必要です。
特徴
- コードの複雑性が大幅に増し、バグの温床になりやすい。
ftplib
が対応していない特殊な FTPS の実装や、デバッグが非常に困難な問題の解決に役立つ可能性がある。- FTPS 接続の全プロセスを細かく制御できる。
この方法が「auth() の代替」として考えられる理由
auth()
が行っている「コントロール接続の TLS 化」というプロセスを、socket
と ssl
モジュールを直接操作して実現するためです。
概念的なコード例 (完全な実装は非常に複雑で省略)
import socket
import ssl
FTP_SERVER = 'your_ftp_server.com'
FTP_PORT = 21 # 明示的FTPSのデフォルトポート
USERNAME = 'your_username'
PASSWORD = 'your_password'
# SSLコンテキストの設定 (ftplibでも使用されるものと同様)
context = ssl.create_default_context()
# 必要に応じて証明書検証を無効化(非推奨)
# context.check_hostname = False
# context.verify_mode = ssl.CERT_NONE
try:
# 1. 通常のTCPソケットを作成し、FTPサーバーに接続
sock = socket.create_connection((FTP_SERVER, FTP_PORT), timeout=30)
ftp_socket_file = sock.makefile('rw', encoding='utf-8', newline='\r\n')
# サーバーからの最初のウェルカムメッセージを読み取る
print(ftp_socket_file.readline().strip())
# 2. AUTH TLS コマンドを送信
ftp_socket_file.write("AUTH TLS\r\n")
ftp_socket_file.flush()
response = ftp_socket_file.readline().strip()
print(f"AUTH TLS 応答: {response}")
# サーバーが TLS 認証の準備ができたことを示す応答 (234) を確認
if not response.startswith('234'):
raise Exception(f"サーバーが TLS 認証を拒否しました: {response}")
# 3. ソケットを SSL/TLS でラップする
# これにより、コントロール接続が暗号化される
ssl_sock = context.wrap_socket(sock, server_hostname=FTP_SERVER)
# 以降の通信は ssl_sock を通じて行われる
ftp_ssl_socket_file = ssl_sock.makefile('rw', encoding='utf-8', newline='\r\n')
# 4. 暗号化された接続上で USER/PASS コマンドを送信し、ログイン
ftp_ssl_socket_file.write(f"USER {USERNAME}\r\n")
ftp_ssl_socket_file.flush()
print(f"USER 応答: {ftp_ssl_socket_file.readline().strip()}")
ftp_ssl_socket_file.write(f"PASS {PASSWORD}\r\n")
ftp_ssl_socket_file.flush()
login_response = ftp_ssl_socket_file.readline().strip()
print(f"PASS 応答: {login_response}")
if not login_response.startswith('230'):
raise Exception(f"ログイン失敗: {login_response}")
print("コントロール接続がTLSで保護され、ログイン成功。")
# 5. データ接続も保護するための PROT P コマンド (非常に複雑になるため、ここでは省略)
# 通常は PASV コマンドを発行してデータポートを取得し、そのソケットも TLS でラップする必要がある
# 6. FTP 操作の実行 (例: PWD)
ftp_ssl_socket_file.write("PWD\r\n")
ftp_ssl_socket_file.flush()
print(f"PWD 応答: {ftp_ssl_socket_file.readline().strip()}")
# 7. 接続の終了
ftp_ssl_socket_file.write("QUIT\r\n")
ftp_ssl_socket_file.flush()
print(f"QUIT 応答: {ftp_ssl_socket_file.readline().strip()}")
ssl_sock.close()
sock.close()
print("FTP接続が正常に終了しました。")
except Exception as e:
print(f"エラーが発生しました: {e}")
この低レベルな方法の課題:
- 利便性の欠如:
ftplib
が提供するstorbinary
,retrbinary
,nlst
,dir
などの便利なメソッドが使えない。 - データ接続: FTP のデータ接続 (ファイル転送用) も TLS で保護するには、
PROT P
コマンドの送信後、PASV
(パッシブモード) またはPORT
(アクティブモード) でデータポートを取得し、そのデータポートへの新しいソケット接続もssl.wrap_socket
でラップする必要があります。これは非常に複雑です。 - エラーハンドリング: タイムアウト、ネットワークエラー、FTP サーバーからの予期せぬ応答など、あらゆるエラーケースに対応する必要がある。
- プロトコル知識: FTP プロトコルの詳細なコマンドと応答コードをすべて理解する必要がある (
PASV
,PORT
,RETR
,STOR
など)。
「ftplib.FTP_TLS.auth()
の代替方法」として最も実用的で推奨されるのは、ftplib.FTP_TLS
クラスを通常通り使用し、login()
メソッドを呼び出すことです。これにより、auth()
の機能は自動的に提供され、安全な FTPS 接続を簡単に確立できます。