ラズパイでiptablesを使って有線LANを中継するスイッチングハブ的なNATコンバータを作る


※ 当ページには【広告/PR】を含む場合があります。
2022/04/21
蛸壺の中の工作室|ラズパイでiptablesを使って有線LANを中継するスイッチングハブ的なNATコンバータを作る

インターネットで「ラズパイ ルーター化」や「ラズパイ スイッチング化」検索すると、様々関連でやられている方々の技術記事を拝見できます。

ご家庭でのネットワーク事情も様々あり、ラズパイの使い方は似ているようで何処か違うので、一概に同じとは言えませんが、今回のこの記事でやりたいものは以下の模式図のような
「有線LANしかないデスクトップパソコンを、ラズパイに有線接続させて、そのラズパイがWiFi接続でインターネットへ中継してくれる」ような使い方を目指します。

合同会社タコスキングダム|蛸壺の中の工作室


ラズベリーパイ4B 4GB 技適対応品

LABISTS Raspberry4 4B-32GB オールインワンセット

TP-Link WiFi 無線LAN 中継器 11ac AC750 433+300Mbps

ラズパイのインターネット中継機かの種類

目標に応じては、ネットワーク構築用のソフトウェアの補助が必要になってくるかも知れません。

ラズパイを「WiFiルーター」「WiFiアクセスポイント」化したい場合には、
hostapdというパッケージが利用されることが多いようです。

ラズパイをアクセスポイント化することで、WiFi無線接続の出来る子機を複数台接続して、ラズパイを経由して外部のネットワークにアクセスすることが出来るようになります。

もう一つの方式はネットワークブリッジを構築するやり方です。

ラズパイのネットワークと、他のインターネットに接続させたいネットワーク同士をブリッジさせれば、比較的簡単にインターネットを共有できます。

つまりラズパイを「スイッチングハブ」化したいときに利用できるのが、ブリッジ方式の良いところですが、ラズパイには基本有線LANポートが1つしか無いので、物理的に複数台の有線LAN機を接続しようと思うと、USB-LAN変換デバイスや、スイッチングハブのようなハードを増設する必要もあるのが難点です。

簡単にネットワークブリッジを設定するためのツールとして有名なのが、
bridge-utilsというパッケージソフトというものがあります。

巷にはとても便利なネットワーキングツールが存在しているとはいえ、よりネットワークなどを理解するためには、今回のお題はとても良い課題といえます。

ということでラズパイに接続するデスクトップを1台に絞って、手動で
iptablesコマンドからNATコンバータとしてカスタマイズしてみます。

参考サイト

ラズパイをWifiルーター化した話

Raspberry piでbridgeを作成


ラズベリーパイ4B 4GB 技適対応品

LABISTS Raspberry4 4B-32GB オールインワンセット

TP-Link WiFi 無線LAN 中継器 11ac AC750 433+300Mbps

ラズパイをルーター化する

では冒頭で挙げていた今回目指す自宅のネットワーク構成の模式図を再喝します。

合同会社タコスキングダム|蛸壺の中の工作室

ここでは自宅に元からあるブロードバンドルーター機器から構築されたネットワークを、例として
192.168.0.0/24ネットワークとします。

普段はこのネットワークを使って複数のパソコンやスマホなどをWiFiや有線LAN接続で利用しています。

一般的に、任意のネットワークから、そことは別のネットワークにポートフォワードによってネットワーク間共有を行うことを考慮すると、別のネットワークの構築用にも別のルーター機器を用意する必要があります。

ということで今回は手持ちのラズパイをルーター化して、新規に
192.168.21.0/24ネットワークを構築するところから作業を始めます。

さらに
192.168.21.0/24ネットワークを構築した上で、このラズパイの「NATコンバータ」化の手順を考えます。

この「NATコンバータ」という意味は、上の模式図の示す通り、「
192.168.0.0/24ネットワークと192.168.21.0/24ネットワークのパケットを交換できる」ような機能をもったルーターを指しています。

重要なことは、以下のようにこのラズパイ存在する2つのインターフェイス(
wlan0とeth0)が、それぞれ別のネットワークに所属するという構成になっているということです。

            wlan0 (WiFi):
    192.168.0.2

eth0 (有線LANアダプタ):
    192.168.21.1
        
ということで以降では、先にwlan0側は既にインターネットへ接続できるようにしておいて、eth0側に192.168.21.0/24ネットワークを構築する流れで説明していきます。

ラズパイのwlan0(WiFi)をIP固定する

ラズパイでインターネットに繋げる側のネットワークの設定を行っていきます。

ここらへんの作業は以前のブログの回で初期設定として取り上げていましたので詳細は省きます。

合同会社タコスキングダム|タコツボの中の工作室
【Raspberry Piセットアップ方法(旧式)】ラズパイ & Remmina on LinuxでRDP接続してリモートデスクトップさせてみる

ラズパイにリモートデスクトップを導入するまでの手順をまとめます。

では
wlan0のIP値を192.168.0.2で固定するために/etc/dhcpcd.confに以下の内容を追記します。

            #...中略

interface wlan0
static ip_address=192.168.0.2/24
static routers=192.168.0.1
static domain_name_servers=192.168.0.1
        
編集後にこの設定を反映させます。

            $ sudo systemctl restart dhcpcd
        
これでインターネットに繋がるかを確認しておきましょう。

ラズパイのeth0をIP固定する

続いてラズパイをルーター化する前に、有線LANのインターフェイスである
eth0も、以下の諸元でIP固定しておきましょう。

このeth0には
192.168.21.0ネットワークのデフォルトゲートウェイの役割を与えるために192.168.21.1を割り当てに使います。

再度
/etc/dhcpcd.confの末尾へ追記します。

            #...中略

denyinterfaces eth0
interface eth0
static ip_address=192.168.21.1/24
static routers=0.0.0.0
static domain_name_servers=0.0.0.0
        

ラズパイにDHCP・DNSサーバーを導入する

次にラズパイをルーター化するため、DHCPサーバおよびDNSサーバーを導入します。

            $ sudo apt install -y isc-dhcp-server dnsmasq
        
今回はラズパイのDHCPサーバーでよく目にするisc-dhcp-serverと、軽量なDNSサーバーdnsmasqをインストールして使います。

本記事の内容ではラズパイに直接デスクトップを1台しか繋ぎませんが、今後の拡張を考えてDHCPで
192.168.21.2 ~ 192.168.21.99までのアドレスを付与するようにしてみます。

以下のように
/etc/dhcp/dhcpd.confにDHCPサーバーの設定を編集していきましょう。

            #...中略

#👇コメントアウト
#option domain-name "example.org";
#👇コメントアウト
#option domain-name-servers ns1.example.org, ns2.example.org;

#👇#を外して有効化
authoritative;

#👇追記
subnet 192.168.21.0 netmask 255.255.255.0 {
    range 192.168.21.2 192.168.21.99;
    option routers 192.168.21.1;
    option domain-name-servers 192.168.21.1;
    option broadcast-address 192.168.21.255;
    ignore declines;
}
        

このDHCPサーバーの設定をeth0へ紐付けします。

            #...中略

#👇ターゲットインターフェイスを指定
INTERFACESv4="eth0"

#...略
        
次にDNSサーバーも設定確認していきます。

/etc/dnsmasq.confというファイルの末尾に以下を追記してみます。

            #...中略

server=8.8.8.8
interface=eth0
        
以上、DHCP・DNSサーバーの設定を終えたら、isc-dhcp-serverとdnsmasqのサービスを常駐化させます。

            $ sudo systemctl start isc-dhcp-server
$ sudo systemctl enable isc-dhcp-server
$ sudo systemctl start dnsmasq
$ sudo systemctl enable dnsmasq
        
ここで一度ラズパイを再起動して、DCHPサーバーおよびDNSサーバーが立ち上がるかを確認しておきましょう。

            $ sudo systemctl status isc-dhcp-server
$ sudo systemctl status dnsmasq
        
後はポートフォワーディングの設定を適切に行うことでラズパイがルーター化します。

このポートフォワーディングを行うためのツールこそ、今回の記事の主題でもある
iptablesコマンドと呼ばれるものです。

かなり奥深いソフトウェアですので、使い方を軽くまとめながら次の節で設定手順を説明します。

ここまでの参考サイト

RASPI で WiFi to 有線 イーサネットコンバータ を作ってみました。

Raspberry Piで無線LANイーサネットコンバータ兼簡易ルータを作る


ラズベリーパイ4B 4GB 技適対応品

LABISTS Raspberry4 4B-32GB オールインワンセット

TP-Link WiFi 無線LAN 中継器 11ac AC750 433+300Mbps

iptablesコマンドでwlan0とeth0を正しくポートフォワードさせる

今回の話の肝として、iptablesの使い方を理解することにあります。

この節で基本的なiptablesコマンドの概要・用法を先に説明していきます。

なおiptablesコマンドを十分理解していらっしゃる方であれば、基礎的な内容をスキップしてもらって、
ラズパイルーター化の作業の続きからお読みください。

iptablesコマンドのインストール

デフォルトではiptablesはインストールされていないので、Raspberry Pi OSに導入する場合、

            $ sudo apt install iptables
        
から使えるようになります。

iptablesのテーブルモデル

iptablesのルーティングモデルで最小構造の模式図を以下に示します。

合同会社タコスキングダム|蛸壺の中の工作室

今回の内容ではローカルプロセスでのパケット介入処理(
INPUT/OUTPUTの各チェイン)は行わないので説明はしませんが、パケットでログを取ったり、不正なパケットを棄却したりするファイヤーウォールを独自に作成したときに使うようです。

今回は
FORWARD/PREROUTING/POSTROUTINGチェインの概要を主として簡単な用途の説明をしていきます。

FORWARDチェイン

まず最も理解のしやすい
FORWARDチェインから説明します。

このルールは発信元・
-i <インターフェイスやIPアドレス>から送信先・-o <インターフェイスやIPアドレス>へのパケットを転送する・しない(ACCEPT/DROP)を決めるルールです。

FORWARDチェインを追加すると、LAN内でパケットがどのようにルーティングされるかを細かく制御することが可能です。

例えば、ネットワークのルーターのデフォルトゲートウェイをもつインターフェイスが
eth0にある場合、このeth0から全てのパケットを出入りを許可したいなら、次のようなFORWARDチェインを設定することになります。

            $ iptables -A FORWARD -i eth0 -j ACCEPT
$ iptables -A FORWARD -o eth0 -j ACCEPT
        
このルールで、デフォルトゲートウェイの所属する内部ネットワークへのアクセスが許可されます。

FORWARDの用法として良く見かけるのは、LANネットワーク内部で使用しているファイル共有などのローカルなサービスが誤って、外部に漏洩しないように
-j DROPで棄却するような使い方もあります。

            #👇外部(0.0.0.0/0)に出ようとする1335~1359番のTCPパケットを棄却
$ iptables -A FORWARD -j DROP -d 0.0.0.0/0 -p tcp --dport 1335:1359
#👇外部(0.0.0.0/0)に出ようとする4465番のUDPパケットを棄却
$ iptables -A FORWARD -j DROP -d 0.0.0.0/0 -p udp --dport 4465
        
なお、たまに使う-m state --stateオプションを指定すると、パケットの状態でさらに細かくルールを適用させたい条件を指定できます。

            -m state --state NEW:
    新規に開始するパケットに適用
-m state --state ESTABLISHED:
    確立済みパケットに適用
-m state --state RELATED:
    既存の接続に対するパケットに適用
-m state --state INVALID:
    不当なパケット
        

POSTROUTING(SNAT)の設定作法

SNATは送信元(Source)のアドレスを変換するNATであり、POSTROUTINGチェインでルール付します。

POSTROUTINGチェインとはインターフェイスからパケットが送信される際の変換ルール決める、送信側デバイスの設定を記述します。

例えば、送信元のアドレスが
192.168.1.123というパケットを受けとったルーター(eth0)が、そのパケットを転送するときに、その送信元のアドレスを書き換えるルールを作成できます。

            $ iptables -t nat -A POSTROUTING -o eth0 -s 192.168.1.123/24 -j MASQUERADE
        
この書き換えに使われるオプションとして、-j MASQUERADE(マスカレード変換: 内部から外部へのパケットのアドレス変換)を指定すると殆どの場合上手くいきます。

MASQUERADEでは、例えばパケットがブロードバンドルーターから外部へ出る際に、送信アドレスがグローバルIPアドレスに自動で変換されます。

ということで、管理者がどのアドレスやポート番号に置き換えればよいのかを逐一判断する必要がなくなります。

マスカレードを使わないで、明示に発信元アドレスの書き換えを行う場合に
-j SNAT(SNAT変換)を使うことになります。

POSTROUTINGでつかうパラメータとして、

            -t nat:
    NATテーブルを使用
-A POSTROUTING:
    POSTROUTINGチェインを追加。
    ネットワーク内部から外部へ出ていくパケットのソース側のIPのを書き換え
-s <発信元のIPアドレス>:
    ソース側のアドレス
-j MASQUERADE/SNAT:
    マスカレードor特定のIPでの書換え方法の指定
-o <出力先インターフェイス>:
    パケットが出ていくインターフェイスを限定する際にインターフェイス名で指定。
    今回はインターフェイスの対応が一対一で明らかであるので省略
        
をそれぞれ指定しています。

変更後の内容が反映されているか、natテーブルの
Chain POSTROUTINGの項目を確認しておきます。

            $ sudo iptables -t nat -n -L

#...中略

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
#👇この行が追加されている
MASQUERADE  all  --  192.168.1.0/24       0.0.0.0/0

#...以下略
        
ここでMASQUERADEよって192.168.1.0/24ネットワークが自動で判別されて追加されていることが確認できます。

PREROUTING(DNAT)の設定作法

SNATの対になる変換にDNATが存在します。

DNATは送信先(Destination)のアドレスを変換するNATで、
PREROUTINGチェインから設定することができます。

このPREROUTINGチェインによって、パケットの受信時にそのパケットを何処に転送すると良いのかがNATテーブルのルールによって変換されることになります。

例えば、wlan0インターフェイス入力されるパケットに対して、宛先が
192.168.1.2だったものを、192.168.1.123に変換するルールを作りたいとなると以下のようにできます。

            $ sudo iptables -t nat -A PREROUTING -d 192.168.1.2 -i wlan0 -j DNAT --to 192.168.1.123
        
ここでもitablesに色々とパラメータが付いています。

            -t nat:
    NATテーブルを使用
-A PREROUTING:
    PREROUTINGチェインを追加。
    ネットワーク外部から内部へ入ってくるパケットのディスティネーション側のIPのを書き換え
-d <送信先のIPアドレス>:
    ディスティネーション側のアドレス
-j DNAT:
    DNATの使用
-i <入力先インターフェイス>:
    パケットが入ってくるインターフェイスを限定する際にインターフェイス名で指定。
    今回はインターフェイスの対応が一対一で明らかであるので省略
        
DNATを作成したら、NATテーブルを確認してみます。

            $ sudo iptables -t nat -n -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
#👇この行が追加されている
DNAT       all  --  0.0.0.0/0            192.168.1.1          to:192.168.1.123

#...省略
        
これでDNATがPREROUTINGテーブルに作成されていることが分かります。

iptablesコマンドからポートフォワーディング

では話を
「ラズパイのルーター化」に戻しましょう。

前節ではネットワークインターフェイスのIP固定、DHCP/DNSサーバーの設定まで終わりました。

続きとして、
ポートフォワードの設定からやっていきます。

ラズパイの
eth0側に接続されたパソコンからのパケットは全て一旦eth0へ送られることになります。

ということで、eth0に割り振られていた
192.168.21.1192.168.21.0ネットワークのデフォルトゲートウェイになります。

このデフォルトゲートウェイを基点に、別のネットワーク(
192.168.0.0ネットワーク)にあるwlan0(192.168.0.2)へ転送されることで初めて、192.168.21.0ネットワークも外部のインターネットに接続できるようにできます。

その「転送」のことを
ポートフォワードと呼んでいます。

ポートフォワード機能をラズパイ側に設定していない状態のままであれば、接続されたPCからのリクエストを何処に転送していいのか分からないままなので、
192.168.21.0ネットワークの外部へのアクセスが開始されることはありません。

ということでこのポートフォワードを有効化してみます。

/etc/sysctl.confの中身を編集し、コメントアウトされているnet.ipv4.ip_forward=1を有効(#を削除)にします。

            #...中略

net.ipv4.ip_forward=1

#...以下略
        
この/etc/sysctl.confを書き換えた後で、以下のコマンドを叩くと設定を反映させることができます。

            $ sudo sysctl -p
        
これでラズパイのポートフォワード機能が開始されます。

rc.localにiptablesコマンドを書き込む

では今回の話で最も重要な設定を行います。

/etc/rc.localファイルに以下のようなルーティングチェインを仕込んでみます。

            #...中略

#👇exit0の手前に追記
iptables -A FORWARD -i eth0 -o wlan0 -j ACCEPT
iptables -A FORWARD -i wlan0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE

exit0
        
ここで最初2つのFORWARDチェインでは、「eth0から入ってきたパケットをwlan0へ転送する」ルールと「wlan0から入ってきたパケットをeth0へ転送する」ルールの合わせ技になっています。

これでwlan0とeth0が相互に通信されるようになります。

最後の3つめの
POSTROUTINGチェインで、「ラズパイから送られる全てのパケットの送信元をwlan0として扱う」ルールになります。

このルールが無いと、外部に繋がっている
192.168.0.0ネットワークに所属していないeth0が送信元になってしまい、192.168.0.0ネットワークのルーター(192.168.0.1)は、何処に応答を返せば良いか分からずに、無効のパケットとして棄却(DROP)されてしまいます。

よって、SNATとしてラズパイから出ていく全てのパケットの送信元をwlan0(
192.168.0.2)として変換することで通信が受領(ACCEPT)されるようにすることが出来きます。

これで
rc.localを書き換えて、ラズパイを再起動させると、ラズパイのeth0側に接続した192.168.21.0ネットワークも外部のインターネットに繋がるようになります。

余談〜rc.localにiptablesコマンドを書き込まないNAT設定の保存方法

では、iptablesコマンドからSNAT/DNATを手動で設定した場合、基本的にはそのセッションだけのルーティングテーブルが構築できるだけですので、ラズパイを再起動するとこの設定はリセットされてしまいます。

このため、先程説明したようにテーブルの設定を永続化するためには、
/etc/rc.localから起動のたびにこのコマンドを実行させる必要がありました。

中には
/etc/rc.localの中身をあまり汚染したくないかたもいると思います。

代替手段として、
iptables-saveiptables-restoreコマンドから起動時に、記録済みのiptablesの設定を読み出す方法もあります。

まずは手動で設定したルーティングテーブルの内容を下記のコマンドで保存しておきます。

            $ sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"
        
次に/etc/rc.localexit 0より前の行に以下の内容で編集します。

            #...中略

#👇exit0の手前に追加する
iptables-restore < /etc/iptables.ipv4.nat

exit 0
        
これでラズパイの再起動のたびに、/etc/iptables.ipv4.natの内容からポートフォワードの設定が復元されることになります。

これで正常に動作していれば、無事ラズパイをイーサネットコンバーターとして利用できるようになっているはずです。

ここまでの内容で参考にさせていただいたサイト

iptablesによるfirewallの例

natテーブルを利用したLinuxルータの作成

iptablesを利用してNATサーバを構築


ラズベリーパイ4B 4GB 技適対応品

LABISTS Raspberry4 4B-32GB オールインワンセット

TP-Link WiFi 無線LAN 中継器 11ac AC750 433+300Mbps

実機でのラズパイルーター化の確認

折角ですので、自作ラズパイルーターの動作確認も行います。

ラズパイのeth0へ接続するパソコンのIP固定

早速ラズパイとクライアントとなるLinuxデスクトップPCを有線LANで接続して、外部のインターネットへ繋がるかを簡単にpingしてみます。

DHCPサーバーは機能しているのでパソコン側はIPを固定する必要がないのですが、一応固定化しておきましょう。

デスクトップPC側で、
/etc/dhcpcd.confのように固定しておきます。

            interface enp3s0
static ip_address=192.168.21.2/24
static routers=192.168.21.1#👈ゲートウェイがラズパイのeth0
static domain_name_servers=192.168.21.1#👈DNSもラズパイのeth0
        
IP固定し終わったら、この内容をシステムに反映させるために、

            $ sudo systemctl restart dhcpcd
        
とコマンドを叩きます。

なお、接続テストに用いたデスクトップのインターフェイスの名前は
enp3s0となっていましたが、お手元のパソコンのNICによっては、ベンダーによってデバイス名が異なるので、各自適当なインターフェイスの名前に読み替えてください。

以上、もろもろの準備が整ったのでラズパイへ有線LANを接続します。

ではまずはルーター化したラズパイで動作確認を行います。

            #👇ラズパイのeth0
$ ping 192.168.21.1
#👇eth0に接続中のデスクトップ
$ ping 192.168.21.2
#👇インターネットに接続されている自宅ルーター
$ ping 192.168.0.1
#👇外部のインターネット
$ ping google.com
        
問題がなければ、これが全てパケットロス無しで通るはずです。

で、いよいよ本題のラズパイのeth0に接続したデスクトップから確認です。

            #👇ラズパイのeth0
$ ping 192.168.21.1
#👇ラズパイのwlan0
$ ping 192.168.0.2
#👇インターネットに接続されている自宅ルーター
$ ping 192.168.0.1
#👇外部のインターネット
$ ping google.com
        
が全てping出来ていればラズパイがルーター化がされています。


ラズベリーパイ4B 4GB 技適対応品

LABISTS Raspberry4 4B-32GB オールインワンセット

TP-Link WiFi 無線LAN 中継器 11ac AC750 433+300Mbps

異なるネットワーク間で通信を確立してSSH接続を試みる

上記の内容までで「ラズパイのルーター化」の目的は十分達成しているのですが、実際に使ってみると思わぬ落とし穴が存在しています。

例えば192.168.0.0ネットワークに所属しているパソコンA(
192.168.0.3)から、192.168.21.0ネットワークのパソコンB(192.168.21.2)へは到達できません...。

            #👇パソコンBからパソコンAにpingしてみる
$ ping 192.168.0.3
#...通信可能

#👇パソコンAからパソコンBにpingしてみる
$ ping 192.168.21.2
#...到達しない!
        

合同会社タコスキングダム|蛸壺の中の工作室

というのは、
192.168.0.0ネットワークに所属しているパソコンAは、192.168.21.0ネットワークが何処にあるのか分からないので、ひとまずデフォルトゲートウェイである192.168.0.1のルーターへパケットを送信することになります。

ですが、
192.168.0.1のルーターも192.168.21.0ネットワークの所在は知らないので、そのまま外部のインターネットを探しにいく...ことで永遠にパソコンBには到達しないのです。

これを回避するためには、パソコンAから
192.168.21.2の宛先を、同じネットワークに存在しているラズパイの192.168.0.2へ聞きに行かないといけません。

ですが、パソコンAが
「“192.168.0.2”って“192.168.21.2”がどこか知っている?」とどう聞くのかが次の問題になってきます。

当たり前ですが、パソコンAから同じネットワークにいるラズパイ(
192.168.0.2)にpingするだけなら簡単です。

            #👇パソコンAから192.168.0.2にpingしてみる
$ ping 192.168.0.2
#...到達可能
        
これだと、192.168.21.2が何処にいるのか尋ねていることにはなりません。

結論からいうと、パソコンAから別のネットワークにあるパソコンBには直接pingが出来ないものの、
「プロキシ接続」の考え方から、特定のポートに別のネットワークでの宛先に紐付けをすることで解決できます。

合同会社タコスキングダム|蛸壺の中の工作室

例えば上の模式図のように、ラズパイ側のwlan0側にポート12345番(
192.168.0.2:12345)にパケットが届いたら、パソコンBでsshポートとして既に開放している54321番(192.168.21.2:54321)へ転送するというDNATを書いてみますと、

            $ sudo iptables -t nat -A PREROUTING -m tcp -p tcp -d 192.168.0.2 --dport 12345 -j DNAT --to 192.168.21.2:54321
        
とPREROUTINGチェインを定めると良いでしょう。

しかし、まだこのままだと宛先アドレスを書き換えるだけで、パソコンB(
192.168.21.2)は、パソコンA(192.168.0.3)という知らないネットワークからパケットを受信することになってしまいます。

返答する戻りの宛先は自分のデフォルトゲートウェイであるラズパイのeth0・
192.168.21.1へ送り返すわけですが、今度は送り先不明の192.168.0.3で、パケットは全て転送されずに棄却されてしまいます。

            $ nc -v -w 1 192.168.0.2 -z 12345
nc: connect to 192.168.0.2 port 12345 (tcp) failed: Connection refused
        
なおpingだとポート指定できないので、ポートありの接続確認にはncコマンドを利用します。

ではどうすればパソコンBからの返答が棄却されずに、そのままパソコンAに送り出してもらえるのかというと、SNATのルールで、パソコンBのsshポート54321番(
192.168.21.2:54321)からのパケットなら、送信元アドレスは192.168.21.1に変更する、という変換ルールも付与することになります。

            $ sudo iptables -t nat -A POSTROUTING -m tcp -p tcp -d 192.168.21.2 --dport 54321 -j SNAT --to 192.168.21.1
        
このSSH接続させるための許可をFORWARDチェインを追加します。

            $ sudo iptables -A FORWARD -m tcp -p tcp -d 192.168.21.2 --dport 54321 -j ACCEPT
$ sudo iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
        
ここまでのルーティングテーブルを追加することで、パソコンAからのパソコンBに接続できているかを確かめてみると、

            $ nc -v -w 1 192.168.0.2 -z 12345
Connection to 192.168.0.2 12345 port [tcp/*] succeeded!
        
と接続が成功しています!

例ではSSH(デフォルトではポート22番)を使いましたが、HTTP(デフォルトでポート80番)や他の代表的なポートでも同様の考え方で変換ルールを付与することで、異なったネットワーク間に接続することができます。

最後にここまでの
/etc/rc.localの中身をまとめると。

            #...省略

#👇exit0の手前に追加
iptables -A FORWARD -i eth0 -o wlan0 -j ACCEPT
iptables -A FORWARD -i wlan0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE

iptables -A FORWARD -m tcp -p tcp -d 192.168.21.2 --dport 54321 -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A PREROUTING -m tcp -p tcp -d 192.168.0.2 --dport 12345 -j DNAT --to 192.168.21.2:54321
sudo iptables -t nat -A POSTROUTING -m tcp -p tcp -d 192.168.21.2 --dport 54321 -j SNAT --to 192.168.21.1

exit0
        
ここまで来ると、iptablesもかなり複雑な設定と感じてしまいますが、ある程度使い方に慣れれば、地図を書くような感覚で結構楽しいと感じてしまいます。

ここまでで参考させていただいたサイト

iptablesで特定のポートを別のホストへ転送する方法


ラズベリーパイ4B 4GB 技適対応品

LABISTS Raspberry4 4B-32GB オールインワンセット

TP-Link WiFi 無線LAN 中継器 11ac AC750 433+300Mbps

まとめ

今回はiptablesコマンドを使ってルーターとルーティングテーブルの設定を色々とラズパイ上で弄ってみました。

普段はあまりルーティングテーブルなんてあまり意識することがないと思いますが、使い方を知っておくと非常に便利なツールですので、一度じっくり勉強されてみると新しい発見があるかも知れません。
記事を書いた人

記事の担当:taconocat

ナンデモ系エンジニア

電子工作を身近に知っていただけるように、材料調達からDIYのハウツーまで気になったところをできるだけ細かく記事にしてブログ配信してます。