- 投稿日:2020-02-17T19:23:57+09:00
ファイル操作の基本コマンド
Linuxではあらゆる種類の情報をファイルとして扱うため、
ファイルの操作に慣れておくことはLinuxを使う上でとても重要です。
そこで、今回はファイル操作における基本的なコマンドと、その使い方を紹介していきます。ファイルの操作
1.ファイルの新規作成
touch <作成したいファイル名>
$ touch hoge # hogeという名前のファイルが新規作成されるまた、スペース区切りで複数のファイルを指定することにより、
複数のファイルが作成される。
このように複数のファイルを一度に指定する方法は、これから紹介する
以下のコマンドでも同じように使用できる
- rm : 複数のファイルが削除される
- cat : 複数のファイルが連結して表示される
touch <作成したいファイル名1> <作成したいファイル名2> <作成したいファイル名3>
$ touch hoge1 hoge2 hoge3 # 3つのファイルが1回のコマンド実行で作成される。
2.ファイルの削除
rm <削除するファイルパス>
$ rm hoge # newfileが削除されるなお、rmコマンドを実行してしまうと確認なしにファイルが削除されてしまう。
そのため、削除する前に確認をはさむ場合は-iオプションを付ける。$ rm -i hoge rm: 通常ファイル 'hoge' を削除しますか? # 削除する場合は'y'を、しない場合は'n'を入力する
3.ファイルの上書き
cp <上書き元ファイルパス> <上書きしたいファイルパス>
$ cp hoge1 hoge2 # hoge2がhoge1で上書きされる。こちらもrmコマンド同様に上書き前に確認をはさむ場合は-iオプションを付ける。
$ cp -i hoge1 hoge2 rm: 'hoge2'を上書きしますか? # 上書きする場合は'y'を、しない場合は'n'を入力する
4.ファイルの中身確認
cat <中身を確認するファイル>
$ cat hoge これはテストです。 # hogeに挿入されている内容が表示される。なお、1でも紹介したとおり、catコマンドでは複数のファイルを指定すると、
ファイルの中身が連結されて表示される。
(これはcatがconcatenate(連結する)の略であることから。)また、catコマンドではオプションを付けることによって表示形式を
変更することができる
オプション 説明 -n 行数を表示する -E 行末に$をつけて表示する -b 空白行以外の行を行数とセットで表示 ※注意
catコマンドはファイルの文字コードの取り決めに従って、
数値を文字に置き換えたものを表示している。
そのため、「文字コード以外の数値が含まれているようなファイル」を表示しようとすると
数値を無理やり文字に置き換えようとするため、文字化けが発生する。
これは後で紹介するlessコマンドも同様である。$ cat /bin/pwd # 画像はコマンドの実行結果を一部抜粋したものである。 # ご覧のように文字化けが発生しているのが分かる。catコマンドでもファイルの中身を見ることはできるが、
1画面内に収まりきらないファイルの内容を表示する場合は
lessコマンドを使うことをおすすめする。lessコマンドは長いファイルを1画面ごとに表示し、スクロールバーを
動かさなくても、キーボードだけでファイルを移動して表示することができる。
また、qを押すまではファイル閲覧専用モードなので、ファイルの閲覧だけに
特化しているのもおすすめする理由。less <ファイルパス>
以下がファイルを移動する際に使うキーの一覧である。
キー 実行結果 f、スペースキー 1画面下に移動する b 1画面上に移動する j 1行下に移動する k 1行上に移動する
5.ディレクトリの作成
mkdir <ディレクトリ>
$ mkdir hogedir # hogedirというディレクトリが作成される深いディレクトリを一気に作成したい場合は-pオプションを付ける
$ mkdir -p test/sample/hogedir
6.ディレクトリの削除
ディレクトリの中身が空であるかどうかによって、指定するコマンドが変わってくる。
ディレクトリが空ではない場合
対象となるディレクトリ配下にファイルやディレクトリが存在する場合は
rmコマンドに-rオプションを付けて削除する。rm -r <削除対象ディレクトリパス>
$ ls hogedir dir1 dir2 file1.txt # 削除対象のディレクトリが空ではないことを確認する $ rm -r hogedir # ディレクトリに配置されたファイルも含めて、ディレクトリが削除されるディレクトリが空の場合
rmdirはディレクトリ内にファイル、ディレクトリが配置されていない場合に
使えるコマンドである。
ただし、rmdirは.(ドット)から始まる隠しファイルが含まれていると
実行してもエラーとなる。
そのため、実行前は通常ファイルだけでなく、隠しファイルも含めて
ディレクトリが空であることを確認する。rmdir <削除するディレクトリパス>
$ ls -a hogedir # 隠しファイルも含めてディレクトリが空であることを確認する。 $ rmdir hogedir # 空ディレクトリが削除される
7.ファイル名変更
mv <変更前のファイルパス> <変更後のファイルパス>
2つの引数がどちらともファイルであり、変更後のファイルが存在しない場合は
ファイル名の変更が行われる。
変更後のファイルがすでに存在した場合は、
cpコマンド同様にファイルの上書きが行われる。$ mv hoge1 hoge2 # hoge1の名前がhoge2に変わるまた、ディレクトリでも同じような方法で名前を変更できる。
mv <変更前のディレクトリパス> <変更後のディレクトリパス>
こちらも変更後のディレクトリが存在しない場合に
ディレクトリ名の変更が行われる。
変更後のディレクトリがすでに存在した場合は
8.のような実行結果となる。
8.ディレクトリへの移動
ここでは7.で紹介したmvコマンドを用いる
mv <移動するファイルパス(スペース区切りで複数指定可)> <移動先ディレクトリパス>
このように最後に指定する引数がファイルではなく、ディレクトリである場合には
名前変更ではなく、ディレクトリへの移動が行われる。$ mv hoge1 hoge2 hoge3 hogedir # 3つのファイルがhogedirリに移動するまた、ファイルに限らずディレクトリをディレクトリ配下に移動することも
同じ方法でできる。mv <移動するディレクトリパス(スペース区切りで複数指定可)> <移動先ディレクトリパス>
$ mv hogedir1 hogedir2 # hogedir2配下にhogedir1が移動する。参考書籍
- 投稿日:2020-02-17T17:22:45+09:00
sedコマンドで指定の文字列を削除する方法!!!
Shellscriptを書いていて、sedで指定した完全一致する文字を削除する方法を書きたいと思います。
sed
sed -i -e '/^1.1.1.1$/d' test.txt結果
元ファイル
1.1.1.100 1.1.1.1sed後
1.1.1.1001.1.1.1が消えます。
正規表現の^ $で最初と最後を指定してあげないと1.1.1.1が含まれる文字が消えてしまいます。
そのため、^$の指定がないと上記の1.1.1.100とかも消えます。
以下オプション説明
-i ファイルを直接編集する GNU系のみ
-e スクリプト(コマンド)を追加する
/d dコマンドは行を削除する。正規表現
^ 先頭の文字列
$ 末尾の文字列
- 投稿日:2020-02-17T17:18:15+09:00
AWS Lambda Layersを用いてLambda関数から外部ライブラリを読み込む。Amazon Linux 2のPython環境も整います。(Python3.6、Anaconda)
AWS Consoleにログインし、EC2からAmazon Linux 2を立てます。
インスタンスタイプはt2.microで、確認と作成ボタンをクリックします。※後述しますが、t2.mediumにしてください。
セキュリティーグループは各自で設定してください。SSH接続用に22番ポートを開けておきます。
既存のキーペアを選択、なければ新規作成してください。SSH接続する際に必要です。
インスタンスの作成中です。インスタンスの表示をクリックします。
インスタンスの状態がrunning、ステータスチェックが2/2のチェックになったら完了です。
インスタンスの作成が完了したら、IPv4パブリックIPをコピーして、PuTTYからSSH接続します。
PuTTYを開いて、Host NameのところにIPアドレスを入力してください。
Connection->SSH->Authからキーペアを選択します。PuTTYgenを用いて、.pemから.ppkに変換したものを使用します。
はいをクリックします。
ec2-userでログインできます。
ログインしたら、Pythonのバージョンを確認します。いまだにPython2系がデフォルトになっているようです。
$ python Python 2.7.16 (default, Dec 12 2019, 23:58:22) [GCC 7.3.1 20180712 (Red Hat 7.3.1-6)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> exit()Anacondaをインストールします。AnacondaのサイトからダウンロードURLをコピーします。
ダウンロードURLに対してwgetし、bashでインストールします。
$ wget https://repo.anaconda.com/archive/Anaconda3-2019.10-Linux-x86_64.sh $ bash Anaconda3-2019.10-Linux-x86_64.shEnterで規約を読み、yesを入力。Enterでインストール開始。
Please answer 'yes' or 'no':' >>> yes Anaconda3 will now be installed into this location: /home/ec2-user/anaconda3 - Press ENTER to confirm the location - Press CTRL-C to abort the installation - Or specify a different location belowUnpacking payload ... 0%| | 0/291 [00:00<?, ?it/s]で止まったままになってしまった。
t2.mediumでできるらしいので、インスタンスの停止、インスタンスタイプの変更を行います。
current latest miniconda sh installer for linux hangs on Unpacking payload step #9345Anacondaのインストールができたら、Python3.6環境を作成します。
$ /home/ec2-user/anaconda3/bin/conda create -n py36 python=3.6 $ /home/ec2-user/anaconda3/bin/conda initインスタンスを再起動し、py36環境でpythonフォルダにライブラリをインストールします。
$ conda activate py36 $ mkdir python $ pip install -t ./python requests $ pip install -t ./python ulid-py $ pip install -t ./python pillow $ pip install -t ./python numpy $ pip install -t ./python opencv-python $ pip install -t ./python opencv-contrib-python $ pip install -t ./python pandas $ pip install -t ./python matplotlib $ pip install -t ./python foliumpythonフォルダをzip化します。
$ zip -r GachiLayers.zip pythonzipファイルをS3へアップロードするために、awscliの設定とboto3をインストールします。
$ pip install awscli $ pip install boto3AWS Console の IAM からユーザーを作成し、AWS Access Key と Secret Access Key を取得します。
AmazonS3FullAccessのアクセス権限を与えておきます。
作成に成功したら、aws configure に必要なAWS Access Key と Secret Access Key を取得できるので、大事に保管しておきます。
AWS Configureの設定、AWS Access Key と Secret Access Key を入力します。
$ aws configure AWS Access Key ID [None]: xxxxxxxxxxxxxxxxxxxx AWS Secret Access Key [None]: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Default region name [None]: ap-northeast-1 Default output format [None]: jsonZipファイルをS3へアップロードするためのPythonプログラムを作成します。S3バケットを新規作成しておくこと。
$ vi upload.pyimport boto3 filename = 'GachiLayers.zip' s3 = boto3.resource('s3') obj = s3.Object(<INSERT YOUR BUCKET NAME>, filename) response = obj.put(Body = open(filename, 'rb'))実行します。
$ python upload.pyAWS Console から Lambda を開き、Layersからレイヤーを作成します。
Lambda関数を作成(ランタイムはPython3.6)し、Layerを追加します。
Lamda関数を編集して、ライブラリが読み込まれていることを確認しましょう。
import json import requests import ulid from PIL import Image import numpy as np import cv2 import pandas as pd import matplotlib.pyplot as plt import folium from folium import plugins def lambda_handler(event, context): # TODO implement return { 'statusCode': 200, 'body': json.dumps('Hello from Lambda!') }実行できれば、ライブラリが読み込まれているはずです。
Response: { "statusCode": 200, "body": "\"Hello from Lambda!\"" }お疲れ様でした。終わったらインスタンス消してもいいです。
- 投稿日:2020-02-17T06:25:26+09:00
Dockerのbridge接続の通信フローをnftablesで追う
はじめに
いまさらながらCentOS8でDockerを勉強しはじめました。で、外部ホスト<--->コンテナのパケットの流れを追ってみたくていろいろ調べました。
けど、リクエストは流れが追えたのですが、レスポンスが追えていません。。。
ひとまずリクエストの経路だけまとめます。いろいろ前提条件
検証環境
以下の環境でトレースしています。
- CentOS8(8.1.1911)
- Docker(19.03.5)
- firewalld(0.7.0)
- iptables(1.8.2:nf_tables)
- nftables(0.9.0)
Docker動作環境
userland proxy(docker-proxy)
iptables / nftables によるdockerネットワークの基本的な動作をみたかったので、docker-pxoryを利用していません。(ヘアピンNAT)
以下のファイルを配置して検証しています。/etc/docker/daemon.json{ "userland-proxy": false }docker network and containers
検証環境として、以下のエントリで生成されたものを利用します。
CentOS8で構成したdockerホスト10.254.10.252
、説明はradiusを対象にしていきます。Docker Composeでネットワークサービス群を5分で作れるようにした(dhcp/radius/proxy/tftp/syslog)
以下のコンテナが生成されます。
server app address listen proxy squid 172.20.0.2 8080/tcp syslog rsyslog 172.20.0.3 514/udp radius freeRADIUS 172.20.0.4 1812/udp dhcp ISC-Kea 172.20.0.5 67/udp tftp tftp-server - 69/udp # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b11308767849 infraserv:proxy "/usr/sbin/init" 3 minutes ago Up 3 minutes 0.0.0.0:8080->8080/tcp proxy 33054f8b7d58 infraserv:tftp "/usr/sbin/init" 35 hours ago Up 2 hours tftp 851ea861d04e infraserv:syslog "/usr/sbin/init" 35 hours ago Up 2 hours 0.0.0.0:514->514/udp syslog dd3a657cfda2 infraserv:dhcp "/usr/sbin/init" 35 hours ago Up 2 hours 0.0.0.0:67->67/udp dhcp 7249b9c4f11d infraserv:radius "/usr/sbin/init" 35 hours ago Up 2 hours 0.0.0.0:1812->1812/udp radius以下のパラメータのネットワークが生成されます。
key value name infraserv_infranet subnet 172.20.0.0/24 interface docker1 tftpは
--net=host
な環境で動作しているため、docker network
は以下のような状態です。# docker network inspect infraserv_infranet [ { "Name": "infraserv_infranet", "Id": "7ed8face2e4fec3110384fa3366512f8c78db6e10be6e7271b3d92452aefd254", "Created": "2020-02-15T05:37:59.248249755-05:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.20.0.0/24", "Gateway": "172.20.0.1" } ] }, "Internal": false, "Attachable": true, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "7249b9c4f11de1f986892965671086d20957a6021269a5f5bc6dd85263bc0d70": { "Name": "radius", "EndpointID": "03ae6a9b9ff7817eea101955d2d6ff016982beb65c7dd6631c75c7299682c2dd", "MacAddress": "02:42:ac:14:00:04", "IPv4Address": "172.20.0.4/24", "IPv6Address": "" }, "851ea861d04edeb5f5c2498cc60f58532c87a44592db1f6c51280a8ce27940bd": { "Name": "syslog", "EndpointID": "d18e466d27def913ac74b7555acc9ef79c88c62e62085b50172636546d2e72bb", "MacAddress": "02:42:ac:14:00:03", "IPv4Address": "172.20.0.3/24", "IPv6Address": "" }, "b11308767849c7227fbde53234c1b1816859c8e871fcc98c4fcaacdf7818e89e": { "Name": "proxy", "EndpointID": "ffa6479b4f28c9c1d106970ffa43bd149461b4728b64290541643eb895a02892", "MacAddress": "02:42:ac:14:00:02", "IPv4Address": "172.20.0.2/24", "IPv6Address": "" }, "dd3a657cfda211c08b7c5c2166f10d189986e4779f1dfea227b3afe284cbafec": { "Name": "dhcp", "EndpointID": "7371f4cf652d8b1bdbf2dc1e5e8ae97013a9a70b890c2caa36c2a7cc93b165df", "MacAddress": "02:42:ac:14:00:05", "IPv4Address": "172.20.0.5/24", "IPv6Address": "" } }, "Options": { "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker1" }, "Labels": { "com.docker.compose.network": "infranet", "com.docker.compose.project": "infraserv", "com.docker.compose.version": "1.25.3" } } ]アドレスファミリ
説明を簡略するために、IPv4に絞っています。
Dockerでのパケットの流れについて
通信を追ってみる(radiusの場合)
今回は外部端末(10.254.10.105)から、Dockerホスト(10.254.10.252)あてにradiusのRequestを送付することを例にします。
自ホストに着信した後に転送されるので、注目するchainのhookは prerouting --> forward --> postrouting となります。
そのため、chainのtypeは、filterとnatだけ、に絞って説明します。ルールは
nft list ruleset
から 不要なものを除外してますが、あまり有用な情報でもないので、補足にまとめました。外部端末からのリクエスト(prerouting)
nft list ruleset
からhookがpreroutingのものを抽出すると、以下となります。table ip nat { chain PREROUTING { (1) type nat hook prerouting priority -100; policy accept; (2)-> fib daddr type local COUNTER jump DOCKER } ->(2) chain DOCKER { ↓ meta l4proto udp udp dport 514 COUNTER dnat to 172.20.0.3:514 ↓ meta l4proto udp udp dport 67 COUNTER dnat to 172.20.0.5:67 ↓ meta l4proto tcp tcp dport 8080 COUNTER dnat to 172.20.0.2:8080 (3) meta l4proto udp udp dport 1812 COUNTER dnat to 172.20.0.4:1812 } }現時点での通信は
10.254.10.105:random --> 10.254.10.252:1812
となります。
(1) preroutingをhookしてnatを行うPREROUTINGというchainが選択される
(2) DstAddrはlocalなので、DOCKERというchainに飛ぶ
addr type localは自ホスト(この場合はDockerホスト)が持つアドレスのことで、
今回ならlo:127.0.0.1
ens192:10.254.10.252
docker1:172.20.0.1
のことです。
(3) DstPortは1812なので、DstAddrを172.20.0.4:1812にDNATする
引き続きの処理がないため、policy適用 -> acceptこの時点の通信は
10.254.10.105:random --> 172.20.0.4:1812
となります。
宛先が172.20.0.4に変更されたため、 routing decision により forward の hook へ進むことになります。外部端末からのリクエスト(forward)
nft list ruleset
からhookがforwardのものを抽出すると、以下となります。table ip filter { chain FORWARD { (1) type filter hook forward priority 0; policy drop; (2)-> COUNTER jump DOCKER-USER ->(3)(4)-> COUNTER jump DOCKER-ISOLATION-STAGE-1 ->(5) oifname "docker1" ct state related,established COUNTER accept (6)-> oifname "docker1" COUNTER jump DOCKER iifname "docker1" oifname != "docker1" COUNTER accept iifname "docker1" oifname "docker1" COUNTER accept } ->(4) chain DOCKER-ISOLATION-STAGE-1 { (5)-> COUNTER return } ->(2) chain DOCKER-USER { (3)-> COUNTER return } ->(6) chain DOCKER { ↓ iifname != "docker1" oifname "docker1" meta l4proto udp ip daddr 172.20.0.3 udp dport 514 COUNTER accept ↓ iifname != "docker1" oifname "docker1" meta l4proto udp ip daddr 172.20.0.5 udp dport 67 COUNTER accept ↓ iifname != "docker1" oifname "docker1" meta l4proto tcp ip daddr 172.20.0.2 tcp dport 8080 COUNTER accept (7) iifname != "docker1" oifname "docker1" meta l4proto udp ip daddr 172.20.0.4 udp dport 1812 COUNTER accept } } table inet firewalld { chain filter_FORWARD { (8) type filter hook forward priority 10; policy accept; ↓ ct state established,related accept (9) ct status dnat accept iifname "lo" accept jump filter_FORWARD_IN_ZONES jump filter_FORWARD_OUT_ZONES ct state invalid drop reject with icmpx type admin-prohibited } chain filter_FORWARD_IN_ZONES { iifname "ens192" goto filter_FWDI_public goto filter_FWDI_public } chain filter_FORWARD_OUT_ZONES { oifname "ens192" goto filter_FWDO_public goto filter_FWDO_public } chain filter_FWDI_public { meta l4proto { icmp, ipv6-icmp } accept } chain filter_FWDO_public { jump filter_FWDO_public_allow } chain filter_FWDO_public_allow { ct state new,untracked accept } }現時点での通信は
10.254.10.105:random --> 172.20.0.4:1812
となります。
(1)forwardのhookの中で最も優先順位が高いので、filterを行うFORWARDというchainが選択される(pri:0)
(2)無条件にDOCKER-USERに飛ぶ
(3)なにもせず戻る
(4)無条件にDOCKER-ISOLATION-STAGE-1に飛ぶ
(5)なにもせず戻る
(6)出力IFはdocker1なので、DOCKERに飛ぶ
(7)入力IFはens192、出力IFはdocker1、DstAddrは172.20.0.4:1812なので、accept
regular chain のDOCKERはbase chainのFORWARDから呼び出されている。
DOCKER でacceptした時点で呼び出し元のFORWARDの評価がされ、このchainは終了する。
(8)forwardのhookの中で2番目に優先順位が高いので、filterを行うfilter_FORWARDというchainが選択される(pri:10)
(9)パケットはDNATされているので、accept
この時点の通信は最初と変わらず10.254.10.105:random --> 172.20.0.4:1812
となります。外部端末からのリクエスト(postrouting)
nft list ruleset
からhookがpostroutingのものを抽出すると、以下となります。table ip nat { chain POSTROUTING { (1) type nat hook postrouting priority 100; policy accept; ↓ oifname "docker1" fib saddr type local COUNTER masquerade ↓ oifname != "docker1" ip saddr 172.20.0.0/24 COUNTER masquerade ↓ meta l4proto udp ip saddr 172.20.0.3 ip daddr 172.20.0.3 udp dport 514 COUNTER masquerade ↓ meta l4proto udp ip saddr 172.20.0.5 ip daddr 172.20.0.5 udp dport 67 COUNTER masquerade ↓ meta l4proto tcp ip saddr 172.20.0.2 ip daddr 172.20.0.2 tcp dport 8080 COUNTER masquerade ↓ meta l4proto udp ip saddr 172.20.0.4 ip daddr 172.20.0.4 udp dport 1812 COUNTER masquerade } table ip firewalld { chain nat_POSTROUTING { (2) type nat hook postrouting priority 110; policy accept; (3)-> jump nat_POSTROUTING_ZONES } ->(3) chain nat_POSTROUTING_ZONES { ↓ oifname "ens192" goto nat_POST_public (4)-> goto nat_POST_public } ->(4) chain nat_POST_public { (5)-> jump nat_POST_public_allow } ->(5) chain nat_POST_public_allow { (6) oifname != "lo" masquerade } } }現時点での通信は
10.254.10.105:random --> 172.20.0.4:1812
となります。
(1) postroutingのhookの中で最も優先順位が高いのでnatを行うPOSTROUTINGというchainが選択される(pri:100)
引き続きの処理がないため、policy適用 -> accept
(2) postroutingのhookの中で2番目に優先順位が高いのでnatを行うnat_POSTROUTINGというchainが選択される(pri:110)
(3) 無条件にnat_POSTROUTING_ZONESに飛ぶ
(4) 無条件にnat_POST_publicに飛ぶ
(5) 無条件にnat_POST_public_allowに飛ぶ
(6) 出力IFはdocker1なので、masquerade
gotoで呼び出された先でchainが終了するため、policy適用 -> accept
regular chain のnat_POST_public_allowはregular chain のnat_POST_publicから呼び出されている。
regular chain のnat_POST_publicはregular chain のnat_POSTROUTING_ZONESからgoto命令で呼び出されている。
goto命令で呼び出されたnat_POST_publicの処理が終了した時点で、呼び出したnat_POSTROUTING_ZONESが終了し
それを呼び出したnat_POSTROUTINGも終了しpolicy accept が適用される。masqueradeの処理を受け、最終的には
172.20.0.1:random --> 172.20.0.4:1812
となります。
(docker1から送出されるため、masqueradeで処理されると、送信元アドレスがdocker1になります)radiusによる認証可否
radiusコンテナが受け取るリクエスト
172.20.0.1:random --> 172.20.0.4:1812
radiusサーバはその可否をチェックし、radiusクライアントに返答を返します。
radiusコンテナが返答するレスポンス
172.20.0.4:1812 --> 172.20.0.1:random
外部端末へのレスポンス
力尽きました。。。
nftablesでカウンタを仕掛けてみると、以下のchainを通過する際のアドレスが見えました。
1回の認証のやり取りなので、各chainで1パケットが見えていました。type filter hook prerouting : 172.20.0.4:1812 --> 172.20.0.1:random type filter hook input : 172.20.0.4:1812 --> 10.254.10.105:random type filter hook forward : 172.20.0.4:1812 --> 10.254.10.105:random type filter hook postrouting : 172.20.0.4:1812 --> 10.254.10.105:randomradiusコンテナからの返答は、
172.20.0.4:1812 --> 172.20.0.1:random
であり、
着信時は自分宛の通信に見えるから、hook:input
を通過しているのは分かります。
その後、LocalProcessを通ってforwardに行く、のでしょうか?このあたりからよくわからなくなってしまいました。。。中途半端になってしまった。。。
radiusからの応答パケットの経路がいまひとつわからない。
なぜどのchainのtype:nat
も通らないんだろう。。。
なぜhook:input
とhook:forward
を同時に通っているんだろう。。。
table bridge filter のtype:filter hook:input pri:-200
に入ってるのに
table ip filter のtype:filter hook:input pri:0
には入って行ってないんだよなぁ。
L2のブリッジとL3のIPで違う処理をしているとか?出典
https://knowledge.sakura.ad.jp/22636/
https://ja.wikipedia.org/wiki/Iptables
https://ja.wikipedia.org/wiki/Nftables
https://wiki.archlinux.jp/index.php/Nftables
https://wiki.archlinux.jp/index.php/Iptables
https://wiki.nftables.org/wiki-nftables/index.php/Netfilter_hooks
https://www.frozentux.net/iptables-tutorial/iptables-tutorial.html#TRAVERSINGOFTABLES
https://wiki.archlinux.jp/index.php/Nftables
https://knowledge.sakura.ad.jp/22636/
https://www.codeflow.site/ja/article/a-deep-dive-into-iptables-and-netfilter-architecture
- 投稿日:2020-02-17T04:04:20+09:00
netfilterとfirewalldとiptablesとnftablesの関係
はじめに
netfilterについて少し調べてみました。
いろいろと認識の相違があったことがわかったので、記録します。認識の相違
CentOS8(に限らずだけど)では、以下のことがわかった。
iptablesはiptablesではなくnftablesである
firewall-cmdで設定したルールはiptablesでは表示されない
すべてのルール確認はnftを使うLinuxでのパケットの流れについて
netfilter
netfilterはLinuxでパケットの処理をする基本ルール
インタフェイスで受信したパケットがどんな処理をされていくか、というやつです。netfilter.orgによると、
netfilterは、カーネルモジュールがネットワークスタックにコールバック関数を登録できるようにするLinuxカーネル内の一連のフックです。登録されたコールバック関数は、ネットワークスタック内の各フックを通過するすべてのパケットに対してコールバックされます。
だそうです。ありがとうgoogle翻訳!
つまり、パケットがネットワークスタックを通り抜けるときに、netfilterで定義した「フック」というものにより、何らかの処理を挟み込めるようにした仕組み。ということでしょうか。
netfilterのchain
ネットワークスタックを通り抜ける一連の処理のことをchainと呼びます。
chainは、以下のものから構成されます。
名称 意味 hook (ネットワークスタックの)どの部分 で priority どのような順番 で type どのような処理をする か 基本は以下の図です。
参考:https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg
netfilterのchainのhook
「(ネットワークスタックの)どの部分」で、処理が行われるか、を表現したものが、hookです。
つまり、ひっかけるタイミングを表現しています。上図の中央付近にある、
routing decision
の部分で処理が変わっているのがわかると思います。
流入したパケットが「ローカル宛て」か、「ローカル宛てじゃない(=転送する)」かで、使われるhookが変わります。hookの部分にフォーカスしたものが以下です。
Local process ^ | .-----------. .-----------. | | | Routing | | |-----> input / \---> | Decision |----> output \ --> prerouting --->| Routing | .-----------. \ | Decision | --> postrouting | | / | |---------------> forward --------------------------- .-----------.参考:https://wiki.nftables.org/wiki-nftables/index.php/Netfilter_hooks
つまり、宛先によって、使われるhookが以下の2通りになります。
ローカルあての場合
prerouting -> input -> output -> postrouting転送する場合
prerouting -> forward -> postrouting(このほかにも、ingressというL2へのパケットに対するhookもあるみたいです。)
netfilterのchainのpriority
「どのような順番」で、処理が行われるか、を表現したものが、priorityです。
つまり、各hookの中での処理の順序を表現しています。priorityは正負の数値で表現されますが、別名が定義されています。
dstnatとscrnatはそれぞれ、preroutingとpostroutingのhookでのみ利用可能です。ですが、実体は飽くまで数値です。
通称 定義 priority 利用可能なhook - NF_IP_PRI_RAW_BEFORE_DEFRAG -450 すべて - NF_IP_PRI_CONNTRACK_DEFRAG -400 すべて raw NF_IP_PRI_RAW -300 すべて - NF_IP_PRI_SELINUX_FIRST -225 すべて - NF_IP_PRI_CONNTRACK -200 すべて mangle NF_IP_PRI_MANGLE -150 すべて dstnat NF_IP_PRI_NAT_DST -100 prerouting filter NF_IP_PRI_FILTER 0 すべて security NF_IP_PRI_SECURITY 50 すべて srcnat NF_IP_PRI_NAT_SRC 100 postrouting - NF_IP_PRI_SELINUX_LAST 225 すべて - NF_IP_PRI_CONNTRACK_HELPER 300 すべて 参考:http://git.netfilter.org/nftables/tree/include/linux/netfilter_ipv4.h
参考:https://manpages.debian.org/testing/nftables/nft.8.en.htmlいわゆる「テーブル」ってやつに似てますね。
netfilterのchainのtype
「どのような処理をする」のか、を表現したものが、typeです。
つまり、具体的にパケットをどうするのか、ということを表現しています。
type 利用可能なhook filter すべて nat prerouting,postrouting,input,output route output あれ?こっちも「テーブル」ってやつに似てますね。
だから紛らわしいんだよ!参考:https://www.netfilter.org/projects/nftables/manpage.html
firewalldとiptablesとnftables
netfilterを構成するものについては、上で解説しましたが、じゃあnetfilterをどう操作するの?
ということで、それらを操作するソフトウェアの話です。firewalld ってなんだ?
firewalld が最上位にいて、バックエンドでiptablesもしくはnftablesが動作している。
バックエンドで動作するiptablesもしくはnftablesがnetfilterの操作をしている。古いバージョンの firewalld ではバックエンドに iptables が、
新しいバージョンの firewalld ではバックエンドに nftables が、採用されている。とても分かりやすい。
てか、本稿のタイトルはもはやこれ1枚でいいんではなかろうか。参考:https://firewalld.org/documentation/concepts.html
iptables ってなんだ?
iptablesはnetfilterを操作できるツールだ。
firewalldが導入される前の古いCentOSでは、iptablesをiptables-serviceというものでデーモン化(サービス化?)していた。
つまり、iptablesコマンドでiptablesのルールを直接変更したり、特定のファイルを読み込ませたりすることで、フィルタリングなりNATなりをしていたんだ。CentOS8にもiptablesはあるが、実体はnftablesで動作している。
# iptables --version iptables v1.8.2 (nf_tables)とはいえ、すでに iptables は iptables ではない。
# ll /usr/sbin/iptables lrwxrwxrwx. 1 root root 17 11月 9 03:40 /usr/sbin/iptables -> xtables-nft-multi # man xtables-nft NAME xtables-nft ― iptables using nftables kernel api DESCRIPTION xtables-nft are versions of iptables that use the nftables API. This is a set of tools to help the system administra‐ tor migrate the ruleset from iptables(8), ip6tables(8), arptables(8), and ebtables(8) to nftables(8).iptablesを叩くと、それっぽい書式でルールが見える。
けど、iptablesからは、後述するnftablesで追加したテーブルが見えない。
だから、iptables -L -nv -t nat|filter で表示されるルールと実際の動作が噛み合わないことがある。例えば、Dockerホストからbridge接続されているコンテナへポート転送をするために
firewall-cmd --add-masquerade
としたとき。nftでchainを確認すると、以下の動作が見える。# nft list chain ip firewalld nat_POST_public_allow table ip firewalld { chain nat_POST_public_allow { oifname != "lo" masquerade } }けど、iptablesから firewalld というテーブルは見れない。
# iptables -L -t firewalld iptables v1.8.2 (nf_tables): table 'firewalld' does not exist Perhaps iptables or your kernel needs to be upgraded.
man iptables
でTABLESの部分をみてみると、iptablesでは、決められたキーワードのテーブルしか確認ができない。TABLES There are currently five independent tables (which tables are present at any time depends on the kernel configuration options and which modules are present). -t, --table table The tables are as follows: filter: nat: mangle: raw: security:つまり、firewalldのバックでnftablesが動作している場合、 iptablesで表示したルールは正しくない!
ので、ルール確認は、 iptablesでなくnftを使う!nftables ってなんだ?
nftablesもnetfilterを操作できる、iptabesに置き換わるツールだ。
前述のiptablesと同じような感じで、nftablesもサービス化できるみたいだけど、、、# systemctl status nftables ● nftables.service - Netfilter Tables Loaded: loaded (/usr/lib/systemd/system/nftables.service; disabled; vendor preset: disabled) Active: inactive (dead) Docs: man:nft(8)CentOS8ではfirewalldが動作していて、nftablesが裏で動作しているので、nftablesとしてのデーモンは休んでいるみたい。
その中身は、以下のように、
nft
コマンドでルールのflush(=除去)と設定ファイルの読み込みをしている。
iptablesをデーモン化したときと似ているね。# cat /usr/lib/systemd/system/nftables.service | grep nft Documentation=man:nft(8) ExecStart=/sbin/nft -f /etc/sysconfig/nftables.conf ExecReload=/sbin/nft 'flush ruleset; include "/etc/sysconfig/nftables.conf";' ExecStop=/sbin/nft flush rulesetdebian/arch/ubuntu/fedora では、nftablesのデーモン動作がデフォルトになっているようだ。
参考:https://wiki.nftables.org/wiki-nftables/index.php/Nftables_from_distributions
基本的なnftablesの使い方
nft
nftablesは
nft
というコマンドで提供されます。
nftで設定するルールは、処理そのものであるchainと、chainをひとまとめにしたtableとして表現されます。chainは特定のhookで特定のtypeで表現される処理をまとめたものであり、「(ネットワークスタックの)どの部分」で「どのような順番」で「どのような処理をする」かは、ひとつのchainでまとめられます。
tableは複数のchainをまとめた仮想的なグループとしてとらえます。設定の確認は
nft list
というコマンドを使います。nft list table(s)
設定されているすべてのtableの名称のみ表示します。
# nft list tables table ip filter table ip6 filter (とか、たくさん)指定したtableの設定されているすべてのchainを表示します。
# nft list table ip nat table ip nat { chain PREROUTING { type nat hook prerouting priority -100; policy accept; fib daddr type local counter packets 0 bytes 0 jump DOCKER } (table ip natに含まれるchainがすべて表示されます)nft list chain(s)
設定されているすべてのchainに対して、各chainがどのtableに含まれているか、発動条件である「(ネットワークスタックの)どの部分」で「どのような順番」の処理を行うのか、が表示されます。
(具体的な処理内容は表示されません)# nft list chains table ip filter { chain INPUT { type filter hook input priority 0; policy accept; } chain FORWARD { type filter hook forward priority 0; policy drop; } (たくさん表示されます)指定したchainを表示します
# nft list chain ip filter FORWARD table ip filter { chain FORWARD { type filter hook forward priority 0; policy drop; counter packets 0 bytes 0 jump DOCKER-USER (たくさん表示されます)すべてのルールの表示
設定されているすべてのルールが表示されます。
# nft list ruleset table ip filter { chain INPUT { type filter hook input priority 0; policy accept; } chain FORWARD { type filter hook forward priority 0; policy drop; counter packets 0 bytes 0 jump DOCKER-USER (すごくたくさん表示されます)さいごに
netfilterはじめ、パケットの取り扱いは奥が深い。
これでもまちがった理解をしているかもしれないし、テキトーに設定してもなんとか動いちゃうこともある。
なるべく正しい知識を取り入れたい。
- 投稿日:2020-02-17T03:56:19+09:00
Docker Composeでネットワークサービス群を5分で作れるようにした(dhcp/radius/proxy/tftp/syslog/dns)
はじめに
CentOS7で各種ネットワークサービスを基本設定したメモ(dhcp/radius/proxy/tftp/syslog)
をCentOS8で再構築しました。今回は各サービスをDockerでコンテナに閉じ込めています。自分で使う用に docker-compose を利用したところ、5分くらいで環境のリストアができるようになったので、記録に残します。
更新
DHCPはIPマスカレード環境でうまく動作しなかったので、network_mode を host に修正しました。
パケット内にIPアドレスが埋め込まれており、単純なNAPTだとコンテナ内のアドレスがDHCPサーバとなってしまうため。DNS64とDNSキャッシュの機能を持つ(unbound)も追加しました。
なにができるようになるのか
以下のような環境を作成できます。
docker-compose したホストの同一ポートにバインドしますので、外部端末から
ホストのアドレス:サービスのポート
にアクセスすると、各コンテナに到着します。
また、各種ログを同一ネットワーク上の syslog を待ち受けているコンテナにログを送信するようにしています。以下のコンテナが生成されます。
server app address listen proxy squid 172.20.0.2 8080/tcp syslog rsyslog 172.20.0.3 514/udp radius freeRADIUS 172.20.0.4 1812,1813/udp dns unbound 172.20.0.5 53/udp,tcp dhcp ISC-Kea - 67,68/udp tftp tftp-server - 69/udp # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3d7fec4d9ffd infraserv:dns "/usr/sbin/init" About a minute ago Up 58 seconds 0.0.0.0:53->53/tcp, 0.0.0.0:53->53/udp dns c34f033b140c infraserv:radius "/usr/sbin/init" About a minute ago Up 57 seconds 0.0.0.0:1812-1813->1812-1813/udp radius eb32cce0d7b9 infraserv:dhcp "/usr/sbin/init" About a minute ago Up 59 seconds dhcp fedd69042ec3 infraserv:tftp "/usr/sbin/init" About a minute ago Up 59 seconds tftp 3e033a44c162 infraserv:syslog "/usr/sbin/init" About a minute ago Up 58 seconds 0.0.0.0:514->514/udp syslog d2454fc12ae8 infraserv:proxy "/usr/sbin/init" About a minute ago Up 57 seconds 0.0.0.0:8080->8080/tcp proxy以下のパラメータのネットワークが生成されます。
key value name infraserv_infranet subnet 172.20.0.0/24 interface docker1 tftp/dhcpは
--net=host
な環境で動作しているため、docker network
は以下のような状態です。# docker network inspect infraserv_infranet [ { "Name": "infraserv_infranet", "Id": "58a9c3da443b49416003d4f3ed5192a521c728270826a18da293000ae4b1004e", "Created": "2020-02-19T07:00:15.610028349+09:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.20.0.0/24" } ] }, "Internal": false, "Attachable": true, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "3d7fec4d9ffd315a6fb087b6a7f28453d7009a8eecd60a5110a3f4f7c4e2564c": { "Name": "dns", "EndpointID": "537b189764340697c9ea4f727211df450226a09a65aa24f20f275f56346d52fc", "MacAddress": "02:42:ac:14:00:05", "IPv4Address": "172.20.0.5/24", "IPv6Address": "" }, "3e033a44c1625b7dd30a8a358f40c96594f462a6714caf39d726d4cb401ffcfd": { "Name": "syslog", "EndpointID": "3083640a976bd89e33d0f478eef9e6faa468cecccaea23729cf01f1ba24692f3", "MacAddress": "02:42:ac:14:00:03", "IPv4Address": "172.20.0.3/24", "IPv6Address": "" }, "c34f033b140cee61992bbc3f1d9d652155121a27462aa460413b7be646e0ab6e": { "Name": "radius", "EndpointID": "f3c7bdc9c08fb283681f412996949126fa5f73213f9a265b6371e028efdc0eb1", "MacAddress": "02:42:ac:14:00:04", "IPv4Address": "172.20.0.4/24", "IPv6Address": "" }, "d2454fc12ae861ff3e240ef26c95c55907382465148e1c4b829d48b5af91d60b": { "Name": "proxy", "EndpointID": "b81e9ea373b2fb7e0a68f1d24534fc6ebb78c01e24e6eb838ecd06127307a202", "MacAddress": "02:42:ac:14:00:02", "IPv4Address": "172.20.0.2/24", "IPv6Address": "" } }, "Options": { "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker1" }, "Labels": { "com.docker.compose.network": "infranet", "com.docker.compose.project": "infraserv_new", "com.docker.compose.version": "1.25.3" } } ]初期設定
後続の手順 で設定ファイルの修正をしない場合は、以下のパラメータで各サービスが動作します。
radius
初期状態では以下の2ユーザとenableパスワードが利用できるようになります。
ユーザ名 パスワード 備考 foo bar 通常ユーザでのログイン hoge fuga Cisco機器にログインすると自動で特権に昇格 \$enab15\$ fuga Cisco機器のenableコマンドで遷移する際のパスワード MACアドレスバイパスでは、以下のMACアドレスの場合に、ダイナミックVLAN用のアトリビュートを付与してAcceptされます。
MACアドレス VLAN文字列 112233445566 default_seg aabbccddeeff default_seg DHCP
リース情報
項目 値 リース時間 10時間 DNSサーバ 8.8.8.8 リース対象セグメント
セグメント レンジ GW 10.1.20.0/24 10.1.20.33 - 10.1.20.62 10.1.20.1 10.1.22.0/24 10.1.22.33 - 10.1.20.230 10.1.22.1 Option43によりアクセスポイントに送付するコントローラアドレス
対象 VCI文字列 コントローラアドレス Cisco Cisco AP 10.254.10.201,10.254.10.202 Aruba ArubaAP 10.254.10.206 リクエストを受け付けるIFを設定ファイル
kea-dhcp4.conf
に記載するのですが、デフォルトでens192
としています。
IFの表記が異なる場合には、設定ファイルの修正が必要です。事前準備
CentOS と Docker と Docker Compose があれば、ここの手順はスキップで 作業内容 から始めてください。
CentOS8(10分)
CentOS8は最小構成で問題ありません。
もし手元になければ、 ESXi6.7にCentOS8を最小構成で構築 を参照してください。Docker(5分)
dnf -y update dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo dnf -y --nobest install docker-ce docker-ce-cli containerd.io dnf -y update https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.10-3.2.el7.x86_64.rpm dnf -y update systemctl enable docker systemctl start dockerDocker Compose(1分)
curl -L "https://github.com/docker/compose/releases/download/1.25.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose作業内容
firewall のポリシー追加(10秒)
firewall-cmd --add-service=dns --zone=public --permanent firewall-cmd --add-service=tftp --zone=public --permanent firewall-cmd --add-masquerade --zone=public --permanent firewall-cmd --reload各サービスのDockerコンテナをつくる(5分)
各サービスのDockerfileと設定ファイル、それらをまとめる docker-compose.yml は GitHub にあるものを使います。
git clone https://github.com/bashaway/infraservデフォルトの設定から変更する場合は、以下のエントリなどを参照してください。
設定ファイルの修正なしでもビルドには影響ありません。
ビルド後に修正しても大丈夫ですし。DHCP
DockerでKea DHCPを構築。CiscoとArubaに同時にOption43が渡せるようになった。RADIUS
DockerのFreeRADIUSでCiscoのログイン認証+MAC認証+ダイナミックVLANした(CentOS8)Proxy
DockerでproxyサーバTFTP
DockerでtftpサーバSyslog
Dockerのrsyslogでコンテナ間や他サーバから転送されるログを集約した設定ファイルの修正が終わったら、コンテナをつくります。
cd infraserv docker-compose build docker-compose up -dいらなくなったら
コンテナ削除 docker-compose stop docker-compose rm -f イメージもいらなければ docker-compose rmi -f中身の解説
docker-compose.yml
docker-compose.yml
は、以下のように構成されています。docker-compose.ymlversion: '3' services: proxy: build: ./proxy image: infraserv:proxy container_name: proxy hostname: proxy restart: always networks: infranet: ipv4_address: 172.20.0.2 ports: - 8080:8080 cap_add: - SYS_ADMIN security_opt: - seccomp:unconfined volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro environment: TZ: 'Asia/Tokyo' syslog: build: ./syslog image: infraserv:syslog container_name: syslog hostname: syslog restart: always networks: infranet: ipv4_address: 172.20.0.3 ports: - 514:514/udp cap_add: - SYS_ADMIN security_opt: - seccomp:unconfined volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro environment: TZ: 'Asia/Tokyo' radius: build: ./radius image: infraserv:radius container_name: radius hostname: radius restart: always networks: infranet: ipv4_address: 172.20.0.4 ports: - 1812:1812/udp cap_add: - SYS_ADMIN security_opt: - seccomp:unconfined volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro environment: TZ: 'Asia/Tokyo' dns: build: ./dns image: infraserv:dns container_name: dns hostname: dns restart: always networks: infranet: ipv4_address: 172.20.0.5 ports: - 53:53/udp - 53:53/tcp cap_add: - SYS_ADMIN security_opt: - seccomp:unconfined volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro environment: TZ: 'Asia/Tokyo' tftp: build: ./tftp image: infraserv:tftp container_name: tftp hostname: tftp restart: always network_mode: host cap_add: - SYS_ADMIN security_opt: - seccomp:unconfined volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro environment: TZ: 'Asia/Tokyo' dhcp: build: ./dhcp image: infraserv:dhcp container_name: dhcp hostname: dhcp restart: always network_mode: host cap_add: - SYS_ADMIN security_opt: - seccomp:unconfined volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro environment: TZ: 'Asia/Tokyo' networks: infranet: driver: bridge driver_opts: com.docker.network.bridge.enable_ip_masquerade: "true" com.docker.network.bridge.host_binding_ipv4: "0.0.0.0" com.docker.network.bridge.name: "docker1" ipam: config: - subnet: 172.20.0.0/24さいごに
Dockerでコンテナにしておくと、ホスト機が汚れなくて気持ちいい
出典
- 投稿日:2020-02-17T03:56:19+09:00
Docker Composeでネットワークサービス群を5分で作れるようにした(dhcp/radius/proxy/tftp/syslog)
はじめに
CentOS7で各種ネットワークサービスを基本設定したメモ(dhcp/radius/proxy/tftp/syslog)
をCentOS8で再構築しました。今回は各サービスをDockerでコンテナに閉じ込めています。自分で使う用に docker-compose を利用したところ、5分くらいで環境のリストアができるようになったので、記録に残します。
なにができるようになるのか
以下のような環境を作成できます。
docker-compose したホストの同一ポートにバインドしますので、外部端末から
ホストのアドレス:サービスのポート
にアクセスすると、各コンテナに到着します。
また、proxy,radius,dhcpは各種ログを同一ネットワーク上の syslog を待ち受けているコンテナにログを送信するようにしています。以下のコンテナが生成されます。
server app address listen proxy squid 172.20.0.2 8080/tcp syslog rsyslog 172.20.0.3 514/udp radius freeRADIUS 172.20.0.4 1812/udp dhcp ISC-Kea 172.20.0.5 67/udp tftp tftp-server - 69/udp # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b11308767849 infraserv:proxy "/usr/sbin/init" 3 minutes ago Up 3 minutes 0.0.0.0:8080->8080/tcp proxy 33054f8b7d58 infraserv:tftp "/usr/sbin/init" 35 hours ago Up 2 hours tftp 851ea861d04e infraserv:syslog "/usr/sbin/init" 35 hours ago Up 2 hours 0.0.0.0:514->514/udp syslog dd3a657cfda2 infraserv:dhcp "/usr/sbin/init" 35 hours ago Up 2 hours 0.0.0.0:67->67/udp dhcp 7249b9c4f11d infraserv:radius "/usr/sbin/init" 35 hours ago Up 2 hours 0.0.0.0:1812->1812/udp radius以下のパラメータのネットワークが生成されます。
key value name infraserv_infranet subnet 172.20.0.0/24 interface docker1 tftpは
--net=host
な環境で動作しているため、docker network
は以下のような状態です。# docker network inspect infraserv_infranet [ { "Name": "infraserv_infranet", "Id": "7ed8face2e4fec3110384fa3366512f8c78db6e10be6e7271b3d92452aefd254", "Created": "2020-02-15T05:37:59.248249755-05:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.20.0.0/24", "Gateway": "172.20.0.1" } ] }, "Internal": false, "Attachable": true, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "7249b9c4f11de1f986892965671086d20957a6021269a5f5bc6dd85263bc0d70": { "Name": "radius", "EndpointID": "03ae6a9b9ff7817eea101955d2d6ff016982beb65c7dd6631c75c7299682c2dd", "MacAddress": "02:42:ac:14:00:04", "IPv4Address": "172.20.0.4/24", "IPv6Address": "" }, "851ea861d04edeb5f5c2498cc60f58532c87a44592db1f6c51280a8ce27940bd": { "Name": "syslog", "EndpointID": "d18e466d27def913ac74b7555acc9ef79c88c62e62085b50172636546d2e72bb", "MacAddress": "02:42:ac:14:00:03", "IPv4Address": "172.20.0.3/24", "IPv6Address": "" }, "b11308767849c7227fbde53234c1b1816859c8e871fcc98c4fcaacdf7818e89e": { "Name": "proxy", "EndpointID": "ffa6479b4f28c9c1d106970ffa43bd149461b4728b64290541643eb895a02892", "MacAddress": "02:42:ac:14:00:02", "IPv4Address": "172.20.0.2/24", "IPv6Address": "" }, "dd3a657cfda211c08b7c5c2166f10d189986e4779f1dfea227b3afe284cbafec": { "Name": "dhcp", "EndpointID": "7371f4cf652d8b1bdbf2dc1e5e8ae97013a9a70b890c2caa36c2a7cc93b165df", "MacAddress": "02:42:ac:14:00:05", "IPv4Address": "172.20.0.5/24", "IPv6Address": "" } }, "Options": { "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker1" }, "Labels": { "com.docker.compose.network": "infranet", "com.docker.compose.project": "infraserv", "com.docker.compose.version": "1.25.3" } } ]初期設定
後続の手順 で設定ファイルの修正をしない場合は、以下のパラメータで各サービスが動作します。
radius
初期状態では以下の2ユーザとenableパスワードが利用できるようになります。
ユーザ名 パスワード 備考 foo bar 通常ユーザでのログイン hoge fuga Cisco機器にログインすると自動で特権に昇格 \$enab15\$ fuga Cisco機器のenableコマンドで遷移する際のパスワード MACアドレスバイパスでは、以下のMACアドレスの場合に、ダイナミックVLAN用のアトリビュートを付与してAcceptされます。
MACアドレス VLAN文字列 112233445566 default_seg aabbccddeeff default_seg DHCP
リース情報
項目 値 リース時間 10時間 DNSサーバ 8.8.8.8 リース対象セグメント
セグメント レンジ GW 10.1.20.0/24 10.1.20.33 - 10.1.20.62 10.1.20.1 10.1.22.0/24 10.1.22.33 - 10.1.20.230 10.1.22.1 Option43によりアクセスポイントに送付するコントローラアドレス
対象 VCI文字列 コントローラアドレス Cisco Cisco AP 10.254.10.201,10.254.10.202 Aruba ArubaAP 10.254.10.206 事前準備
CentOS と Docker と Docker Compose があれば、ここの手順はスキップで 作業内容 から始めてください。
CentOS8(10分)
CentOS8は最小構成で問題ありません。
もし手元になければ、 ESXi6.7にCentOS8を最小構成で構築 を参照してください。Docker(5分)
dnf -y update dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo dnf -y --nobest install docker-ce docker-ce-cli containerd.io dnf -y update https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.10-3.2.el7.x86_64.rpm dnf -y update systemctl enable docker systemctl start dockerDocker Compose(1分)
curl -L "https://github.com/docker/compose/releases/download/1.25.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose作業内容
firewall のポリシー追加(10秒)
firewall-cmd --add-service=tftp --zone=public --permanent firewall-cmd --add-masquerade --zone=public --permanent firewall-cmd --reload各サービスのDockerコンテナをつくる(5分)
各サービスのDockerfileと設定ファイル、それらをまとめる docker-compose.yml は GitHub にあるものを使います。
git clone https://github.com/bashaway/infraservデフォルトの設定から変更する場合は、以下のエントリなどを参照してください。
設定ファイルの修正なしでもビルドには影響ありません。
ビルド後に修正しても大丈夫ですし。DHCP
DockerでKea DHCPを構築。CiscoとArubaに同時にOption43が渡せるようになった。RADIUS
DockerのFreeRADIUSでCiscoのログイン認証+MAC認証+ダイナミックVLANした(CentOS8)Proxy
DockerでproxyサーバTFTP
DockerでtftpサーバSyslog
Dockerのrsyslogでコンテナ間や他サーバから転送されるログを集約した設定ファイルの修正が終わったら、コンテナをつくります。
cd infraserv docker-compose build docker-compose up -dいらなくなったら
コンテナ削除 docker-compose stop docker-compose rm -f イメージもいらなければ docker-compose rmi -f中身の解説
docker-compose.yml
docker-compose.yml
は、以下のように構成されています。docker-compose.ymlversion: '3' services: proxy: build: ./proxy image: infraserv:proxy container_name: proxy hostname: proxy restart: always networks: infranet: ipv4_address: 172.20.0.2 ports: - 8080:8080 cap_add: - SYS_ADMIN security_opt: - seccomp:unconfined volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro environment: TZ: 'Asia/Tokyo' syslog: build: ./syslog image: infraserv:syslog container_name: syslog hostname: syslog restart: always networks: infranet: ipv4_address: 172.20.0.3 ports: - 514:514/udp cap_add: - SYS_ADMIN security_opt: - seccomp:unconfined volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro environment: TZ: 'Asia/Tokyo' radius: build: ./radius image: infraserv:radius container_name: radius hostname: radius restart: always networks: infranet: ipv4_address: 172.20.0.4 ports: - 1812:1812/udp cap_add: - SYS_ADMIN security_opt: - seccomp:unconfined volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro environment: TZ: 'Asia/Tokyo' dhcp: build: ./dhcp image: infraserv:dhcp container_name: dhcp hostname: dhcp restart: always networks: infranet: ipv4_address: 172.20.0.5 ports: - 67:67/udp cap_add: - SYS_ADMIN security_opt: - seccomp:unconfined volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro environment: TZ: 'Asia/Tokyo' tftp: build: ./tftp image: infraserv:tftp container_name: tftp hostname: tftp restart: always network_mode: host cap_add: - SYS_ADMIN security_opt: - seccomp:unconfined volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro environment: TZ: 'Asia/Tokyo' networks: infranet: driver: bridge driver_opts: com.docker.network.bridge.enable_ip_masquerade: "true" com.docker.network.bridge.host_binding_ipv4: "0.0.0.0" com.docker.network.bridge.name: "docker1" ipam: config: - subnet: 172.20.0.0/24さいごに
Dockerでコンテナにしておくと、ホスト機が汚れなくて気持ちいい
出典