「インターネット共有」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(→‎トラブルシューティング: クライアントがインターネットにアクセスできない、または接続できないを翻訳して追加)
(リンクを修正)
 
28行目: 28行目:
 
このセクションでは、クライアントのコンピュータに接続するネットワークデバイスの名前は '''''net0'''''、インターネットに接続するネットワークデバイスの名前は '''''internet0''''' としています。
 
このセクションでは、クライアントのコンピュータに接続するネットワークデバイスの名前は '''''net0'''''、インターネットに接続するネットワークデバイスの名前は '''''internet0''''' としています。
   
{{Tip|[[Udev#固定デバイス名設定]]を使ってデバイスの名前は変更することができます。}}
+
{{Tip|[[Udev#固定デバイス名設定する]]を使ってデバイスの名前は変更することができます。}}
   
 
サーバーコンピュータには、最後の [[#クライアント PC に IP アドレスを割り当てる]] ステップを除くすべての設定がされています。
 
サーバーコンピュータには、最後の [[#クライアント PC に IP アドレスを割り当てる]] ステップを除くすべての設定がされています。

2023年12月28日 (木) 12:59時点における最新版

関連記事

この記事ではあるマシンと他のマシンでインターネット接続を共有する方法を解説します。

要件

サーバーとして機能するマシンにはネットワークデバイスを別に設定する必要があります。このネットワークデバイスにはインターネットアクセスにアクセスするマシンへの正常な w:データリンク層 が必要です:

  • 複数のマシンにインターネットを共有するために スイッチ がデータリンク層を提供できます
  • ワイヤレスデバイスも同様に複数のマシンへ接続を共有できます。ソフトウェアアクセスポイント を参照して下さい。
  • 1台のマシンのみと共有する場合は、クロスオーバーケーブル で十分です。2台のコンピュータのイーサネットカードが MDI-X 機能を持つ場合、クロスオーバーケーブルは不要で通常のイーサネットケーブルが使えます。rootで ethtool interface | grep MDI を実行すると判別し易くなります。

設定

このセクションでは、クライアントのコンピュータに接続するネットワークデバイスの名前は net0、インターネットに接続するネットワークデバイスの名前は internet0 としています。

ヒント: Udev#固定デバイス名を設定するを使ってデバイスの名前は変更することができます。

サーバーコンピュータには、最後の #クライアント PC に IP アドレスを割り当てる ステップを除くすべての設定がされています。

固定 IP アドレス

サーバーコンピュータ上で、他のマシンに接続したインターフェイスに固定 IPv4 アドレスを割り当てます。他のインターフェイスのネットマスクが /24 より大きい場合を除き、アドレスの頭3バイトは両インターフェイスのアドレスの頭3バイトと違っている必要があります。

# ip link set up dev net0
# ip addr add 192.168.123.100/24 dev net0 # 任意のアドレス

起動時に固定 ip を割り当てたい場合、ネットワークマネージャ を使います。

パケット転送の有効化

現在のパケット転送の設定をチェック:

# sysctl -a | grep forward

インターフェース毎に別々の IPv4/IPv6 オプションがあるように、デフォルト毎、インターフェース毎に転送を制御するオプションが存在することに注意して下さい。

次のコマンドを実行して一時的にパケット転送を有効化:

# sysctl net.ipv4.ip_forward=1
ヒント: 特定のインターフェイスでのみパケット転送を有効にしたい場合は sysctl net.ipv4.conf.interface_name.forwarding=1 を使ってください。
警告: システムがネットワークインターフェースの制御に systemd-networkd を使っている場合、インターフェース毎の IPv4 設定は不可能です。すなわち、systemd のロジックはどのような転送設定も(全インターフェース用の)IPv4 のグローバル設定へ伝搬します。推奨される回避策は firewall を使って特定のインターフェースに対して転送を禁止することです。詳しくは systemd.network(5) マニュアルページを参照して下さい。以前の systemd リリース 220/221 に導入されたカーネルの設定を優先する IPForward=kernel セマンティクスはもはや適用されません。[1] [2]

再起動した後も設定が残るようにするには /etc/sysctl.d/30-ipforward.conf を編集:

/etc/sysctl.d/30-ipforward.conf
net.ipv4.ip_forward=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1

設定した後は、再起動してから転送が有効になっているか確認するのを推奨します。

NAT の有効化

iptables を使う

公式リポジトリから iptables パッケージをインストールしてください。iptables を使って NAT を有効化:

# iptables -t nat -A POSTROUTING -o internet0 -j MASQUERADE
# iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# iptables -A FORWARD -i net0 -o internet0 -j ACCEPT
ノート: もちろん、上記は移動体通信でも機能します (ルーティング PC では通常 ppp0 になります)。

詳細は iptables の記事を読んで下さい (特に、ルールの保存と、起動時に自動的にルールを適用させる方法の項)。iptables についてはシンプルなステートフルファイアウォールのページでも詳しい解説をしています。

nftables を使う

nftablesインストール して下さい。nftables で NAT を有効にするには、新規/既存のテーブルに prerouting と postrouting チェインを作成する必要があります(両方のチェインが空の場合でも必要):

# nft add table ip nat
# nft add chain ip nat prerouting { type nat hook prerouting priority 0 \; }
# nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }
ノート: IPv6 を使いたい場合、ipip6 で置き換える必要があります。

その後、internet0 用に net0 アドレスをマスカレードする必要があります:

# nft add rule nat postrouting oifname internet0 masquerade

転送に対しさらにいくつかの firewall による制限を追加できます ( Nftables#シンプルな IPv4/IPv6 ファイアウォール で設定されているような、フィルターテーブルが存在することが前提です):

# nft add chain inet filter forward { type filter hook forward priority 0 \; policy drop}
# nft add rule filter forward ct state related,established accept
# nft add rule filter forward iifname net0 oifname internet0 accept

nftables における NAT の詳細は nftables Wiki を見て下さい。変更を永続化するには nftables に従って下さい。

firewalld を使う

firewalld パッケージを インストール します。firewalld は、nftables または iptables に依存するファイアウォールデーモンです。まず、ネットワークインターフェイスの firewalld ゾーンを変更します。

# firewall-cmd --zone=external --change-interface=internet0 --permanent
# firewall-cmd --zone=internal --change-interface=net0 --permanent

次に、新しいポリシーを追加して、内部ゾーンと外部ゾーンの間でトラフィックが流れるようにします。

# firewall-cmd --permanent --new-policy int2ext
# firewall-cmd --permanent --policy int2ext --add-ingress-zone internal
# firewall-cmd --permanent --policy int2ext --add-egress-zone external
# firewall-cmd --permanent --policy int2ext --set-target ACCEPT
# firewall-cmd --reload
ヒント: firewalld コンセプトページ [3]Firewall Rules セクションに示されているように、ACCEPT よりも厳密なポリシールールを使用できます。

たとえば、192.168.2.0/24 内のノードのみがインターネットにアクセスできるようにするには、次のようにします。

firewall-cmd --permanent --policy int2ext --add-rich-rule='rule family=ipv4 source address=192.168.2.0/24 accept' 後でルールを再ロードすることを忘れないでください。

firewall-cmd --reload

クライアント PC に IP アドレスを割り当てる

定期的に、複数のマシンで、設定したマシンのインターネット共有を使う場合、dhcpddnsmasq のような dhcp サーバーをインストールすると良いでしょう。その後、各クライアント PC で DHCP クライアント(例えば dhcpcd)を設定してください。

この記事あるいはセクションで使われている用語や表現には問題が存在します。
議論: This is not an iptables guide. Expanding the chain with iptables -I might skip other important rules; if you need to script an ON/OFF switch for this, use custom chain with a jump placed carefully in the INPUT chain. (議論: トーク:インターネット共有#)

DHCP サーバでは UDP ポート 67 への着信を許可する必要があります。DNS リクエストのために UDP/TCP ポート 53 への着信も許可する必要があります。

# iptables -I INPUT -p udp --dport 67 -i net0 -j ACCEPT
# iptables -I INPUT -p udp --dport 53 -s 192.168.123.0/24 -j ACCEPT
# iptables -I INPUT -p tcp --dport 53 -s 192.168.123.0/24 -j ACCEPT

特に定期的に使うというわけではないのであれば、手動でクライアントに IP を追加する方法もあります。

手動で IP を追加

この記事あるいはセクションで使われている用語や表現には問題が存在します。

DHCP を使う代わりに、クライアント PC で、IP アドレスとデフォルトルートを追加:

# ip addr add 192.168.123.201/24 dev eth0  # 任意のアドレス、最初の3ブロックは前述のアドレスと一致している必要があります
# ip link set up dev eth0
# ip route add default via 192.168.123.100 dev eth0   # 最初と同じアドレス

全てのクライアントで DNS サーバーを設定してください。詳しくは resolv.conf を参照。

これでクライアント PC はインターネットに接続されるはずです。

トラブルシューティング

PC に接続することはできながら、データを送信することはできない場合 (例えば、クライアント PC がサーバー PC に DHCP リクエストを送った場合、サーバー PC はリクエストを受け取ってクライアントに IP を返すが、クライアントがそれを受け取れずに、タイムアウトしてしまう等)、干渉する Iptables ルールが設定されていないか確認してください。

クライアントがインターネットにアクセスできない、または接続できない

以下のような症状。クライアントがホストに ping を打つと host is down となる、LAN 外のデバイス(NAT で転送されるはず)に ping を打つと no route to host となる、DHCP オファーがブリッジを通らない、などです。

docker がこれらの問題を引き起こす可能性があることが知られています。docker.servicedocker.socket停止 するだけでこの問題は解決します。

docker github issue

参照