2018年12月24日月曜日

Ubuntu 18.04LTS で NAT ルータを構築

まあ,数千円で有線ルータが買える時代なのではあるが.
ちょっと思うところがあり,Linux で NAT ルータを組んだ.
Linux をいじり始めた頃,余っていた 386SX のマザーボードにフロッピーディスク1枚で動くというディストリビューションを使って,当時まだ実験中段階だった IP masquerade で,フロア中の PC を一つの IP アドレスでネット接続可能にしたりしたのだった.まだ20世紀のころだな.ベニヤ板に AT 電源とマザボを木ネジで留め,FDD はガムテープで固定,カバーは段ボール.NIC は ISA バスに 2 枚刺し,キーボードもモニタもなし,みたいな.これは最初の設定にちょっと苦労したけど,かなり長期間,実用したのも懐かしい.

ハードウェア

今回のハードには,LAN ポートが複数ついていて,ファンレスな小型マシンが適当.マシンパワーはいらないので,古いノート PC (+USBの ether) というのも考えたが,今回は潔く新規導入.適当に探した中で XCY のベアボーンに4ポートの LAN がついたシリーズを発見.Celeron J1800,2 GB メモリ,32 GB SSD (mSATA) のモデルなら 18,000円だったのでこれを採用.ほかにインターフェースは VGA ×1,USB2.0 ×2.十分である.
Windows 7 プレインストールとのことだが,使わないので本質的ではない.上書きしてもぜんぜんかまわないのだが,ちょうど 32 GB の mSATA SSD (1,200円くらいだった) が手持ちにあったので,これに差し替え.Win7 入りのはそのまま外して保管 (使用予定は特にないが).

OSのインストール

インストールする OS は迷ったが,Ubuntu 18.04 LTS.Server ではなく Desktop を最小構成でインストールすることに.

インストール時には,VGA ポートにモニタをつなぎ,USB のキーボードとマウスをつけて,インストールイメージを焼いた USB メモリから起動.起動時に F11 キーでブートデバイスを選ぶメニューが出るので,USB メモリを選択し,あとは適当に選んでいってインストールを終える.LAN 関係はあとで設定し直すので,この段階では適当でよい.
USB メモリを抜いて,内蔵 SSD から起動し,あれこれ設定に入る.

LAN ポートの設定

このマシンは LAN ポートが四つあるが,当面は二つを使う.ひとつは外とつなぐ側で,これは DHCP で外のネットワークから接続情報を取る.まずこちらを設定して,ふつうに使えるようにしておく.どのポートでもいいのだが,今回は LAN4 を使用.システムからは enp4s0 という名前で見える.ネットワーク設定で IPv4 のところのメソッドを DHCP にしておけば OK.これで既存の LAN に接続して,外を見に行けることを確認.ついでにこの段階で,システムの update/upgrade もしてしまう.

さて,ルータとして使うので,もうひとつのポート,LAN1 (enp1s0),を設定する.このルータの下にぶら下がるプライベート LAN には 192.168.1.0/24 の空間を割り当てる.IPv4 の設定としては,
メソッド: 手動
アドレス: 192.168.1.1
ネットマスク: 255.255.255.0
ゲートウェイ: 192.168.1.1
DNS: 自動
ルート: 自動

DHCPサーバのインストール

このルータの下にぶら下がるネットワークからは,このマシンが DHCP サーバになる.

$ sudo apt install isc-dhcp-server
/etc/dhcp/dhcpd.conf を編集.
以下のコメントを外して有効化.

authorative;
log-facility local7;

以下を設定

subnet 192.168.1.0 netmask 255.255.255.0 {
   range 192.168.1.50 192.168.1.199;
   option domain-name "local";
   option routers 192.168.1.1;
   option broadcast-address 192.168.1.255;
   default-lease-time 432000;
   max-lease-time 864000;
}

上の例ではリース時間をデフォルトで5日,最長10日で設定しているが,最長は無限 (-1 を設定 →参考) でもいいのかも.

IP forward の設定

/etc/sysctl.conf を編集.以下を有効化.

net.ipv4.ip_forward=1

IP masquerade の設定

iptablesの初期化.

$ sudo iptables -t nat -F
$ sudo iptables -F
$ sudo iptables -L

新たな設定.enp1s0 がローカル側,enp4s0 が外側に注意.

$ sudo iptables -t nat -A PORTROUTING -o enp1s0 -j MASQUERADE
$ sudo iptables -A FORWARD -i enp1s0 -o en4s0 -m state --state RELATED,ESTABLISHED -j ACCEPT
$ sudo iptables -A FORWARD -i enp4s0 -o enis0 -j ACCEPT

設定内容をファイルに保存.

$ sudo iptables-save > iptables.dat

保存内容を起動時に読み込むようにするには /etc/rc.local に以下を追加.

iptables-restore < (path)/iptables.dat

(path) は先ほど保存した場所に合わせる.

いったん再起動.
ここまでで,LAN1 に他のマシンをつないで,DHCP で 192.168.1.x のアドレスが振ってくることを確認.また,IPアドレスを直接指定すれば,クライアントから外を見に行けることも確認.

DNS masquerade の設定

ここでハマった.Ubuntu 16.10 あたりで DNS レゾルバが systemd-resolved になった関係で dnsmasq と衝突がおこってしまう (port 53の競合).結局,systemd-resolved を使わないことで解決.
dnsmasq をインストール.

$ sudo apt install dnsmasq

このままでは動かないので,systemd-resolved を停止する.
/etc/systemd/resolved.conf を修正.

[Resolve]
DNSStubListener=no

systemd-resolved を再起動.

$ sudo systemctl restart systemd-resolved

これで,DNS が効かなくなり,このマシンからも名前解決ができなくなる.
/etc/NetworkManager/NetworkManager.conf を修正.
[main] セクションに以下を追加.

dns=dnsmasq

/etc/resolv.conf が systemd-resolved の設定ファイルへのシンボリックリンクなっているのを解除する.

$ sudo unlink /etc/resolv.conf

これで /etc/resolv.conf はなくなるが,NetworkManager を再起動すると勝手にできてくる.

$ sudo systemctl restart NetworkManager

dnsmasq を起動.

$ sudo /etc/init.d/dnsmasq start

あるいはマシンを再起動する.

/etc/dhcp/dhcpd.conf を修正する.192.168.1.0/24 の設定のところに以下を追加.

option domain-name-servers 192.168.1.1;

ローカル側につないだクライアントから名前解決できることを確認.

SSHサーバの設定

実際の運用時には,このマシンはキーボードもモニタもはずした状態になる.したがって,外からログインできるようにしないといけない.sshd は入っていないのでインストールする.

$ sudo apt install openssh-server

このままでは,どちらのネットワークからでも接続できてしまうので,内側からしか接続できないようにする.
/etc/ssh/sshd_config を修正.

ListenAddress 192.168.1.1

修正を反映.

$ sudo /etc/init.d/ssh restart


参考サイト

Ubuntu 16.04 でルータつくる
Ubuntu18.04のDNSリゾルバをsystemd-resolvedからdnsmasqに変更する
ubuntu18.04LTS SSH接続
sshd_configの設定項目の理解を目指す

1 件のコメント:

  1. sudo iptables -t nat -A PORTROUTING -o enp1s0 -j MASQUERADEで
    iptables: No chain/target/match by that name.と出てしまいます。
    アドバイスおねがいします。

    返信削除