Linuxで0.0.0.0:443アクセスが127.0.0.1:443にリダイレクトされる理由とこれを無効にする方法は?

Linuxで0.0.0.0:443アクセスが127.0.0.1:443にリダイレクトされる理由とこれを無効にする方法は?

簡単に言うと:入場0.0.0.0:port(たとえば)(内部的に)(ポート番号はどこにありますか?)curl http://0.0.0.0:443にリダイレクトされます(たとえば、前のコマンドと同じ)。127.0.0.1:portportcurlcurl http://127.0.0.1:443なぜこのようなことが起こりますか?どのように接続をブロックしても0.0.0.0よろしいですか?

アップデート2:Linuxカーネル(バージョン6.0.9)にパッチを適用してこれを防ぐ方法を見つけました。


--- .orig/usr/src/linux/net/ipv4/route.c
+++ /usr/src/linux/net/ipv4/route.c
@@ -2740,14 +2740,17 @@ struct rtable *ip_route_output_key_hash_
    }
 
    if (!fl4->daddr) {
-       fl4->daddr = fl4->saddr;
+           rth = ERR_PTR(-ENETUNREACH);
+           goto out;
+                        /* commenting out the rest:
+       fl4->daddr = fl4->saddr; // if you did specify src address and dest is 0.0.0.0 then set dest=src addr
        if (!fl4->daddr)
-           fl4->daddr = fl4->saddr = htonl(INADDR_LOOPBACK);
+           fl4->daddr = fl4->saddr = htonl(INADDR_LOOPBACK); // if you didn't specify source address and dest address is 0.0.0.0 then make them both 127.0.0.1
        dev_out = net->loopback_dev;
        fl4->flowi4_oif = LOOPBACK_IFINDEX;
        res->type = RTN_LOCAL;
        flags |= RTCF_LOCAL;
-       goto make_route;
+       goto make_route; END of COMMENTed out block */
    }
 
    err = fib_lookup(net, fl4, res, 0);

結果:IP 0.0.0.0に送信されたパケットはどこに行きますか? :

$ ip route get 0.0.0.0
RTNETLINK answers: Network is unreachable

...彼らはしません!

クライアントは127.1.2.18:5000から0.0.0.0:80に接続しようとします。

$ nc -n -s 127.1.2.18 -p 5000 -vvvvvvvv -- 0.0.0.0 80
(UNKNOWN) [0.0.0.0] 80 (http) : Network is unreachable
 sent 0, rcvd 0

(カーネルパッチを適用していない場合、上記のクライアントが正常に接続するには、次のサーバーが必要です:(rootとして、bashで)while true; do nc -n -l -p 80 -s 127.1.2.18 -vvvvvvvv -- 127.1.2.18 5000; echo "------------------$(date)";sleep 1; done

修正済みping(つまり、ping宛先アドレスが0.0.0.0の場合、宛先アドレスをソースアドレスと同じに設定しない、つまり、// special case for 0 dst address下に示す2行をコメントアウトします)ここ):

$ ping -c1 0.0.0.0
ping: connect: Network is unreachable

即時。ただし、送信元アドレスを指定した場合は、完了するにはタイムアウト(10秒)が必要です。

$ ping -I 127.1.2.3 -c1 -- 0.0.0.0
PING 0.0.0.0 (0.0.0.0) from 127.1.2.3 : 56(84) bytes of data.

--- 0.0.0.0 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

アップデート1:

これなぜ部分的に説明ここしかし、なぜこれが起こるのかについての詳細を期待しています。たとえば、(anyoneliberachat#kernelチャンネルでニックネームを持つユーザーに感謝します):

$ ip route get 0.0.0.0
local 0.0.0.0 dev lo src 127.0.0.1 uid 1000
    cache <local>

これは、何らかの方法でlocalhostに向けられたパケットが0.0.0.0localhostインターフェイスにルーティングされ、loソースIPを取得し127.0.0.1(正しく解釈された場合)、そのルートのためにこのリストに表示されないことを意味します。

$ ip route list table local
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1
local 169.254.6.5 dev em1 proto kernel scope host src 169.254.6.5
broadcast 169.254.6.255 dev em1 proto kernel scope link src 169.254.6.5
local 192.168.0.17 dev em1 proto kernel scope host src 192.168.0.17
broadcast 192.168.255.255 dev em1 proto kernel scope link src 192.168.0.17

これは、これがどういうわけかLinuxカーネル内に存在しなければならないことを意味します。つまり。ハードコーディング

アイデアを提供するために、インターネット上でIPを見つける方法は次のとおりです(例IPとしてQuad1を使用しました)。

$ ip route get 1.1.1.1
1.1.1.1 via 192.168.1.1 dev em1 src 192.168.0.17 uid 1000
    cache

私のゲートウェイはどこにありますか192.168.1.1

$ ip route
default via 192.168.1.1 dev em1 metric 2
169.254.6.0/24 dev em1 proto kernel scope link src 169.254.6.5
192.168.0.0/16 dev em1 proto kernel scope link src 192.168.0.17

0.0.0.0に向かって何らかの方法で127.0.0.1にルーティングされる接続を検出(したがってブロック/削除)する方法がないため、ブロックするiptables方法を見つけるのは難しい場合があります。しかし、確かに見つけようとします。誰かがすでに知っていない限り、1つの方法です。

@Stephen Kitt(コメントでは)は/ etc / hostsのホスト名をブロックする方法を提案したので(127.0.0.1以外の名前)
0.0.0.0 someblockedhostname
使用できますが、
127.1.2.3 someblockedhostname
127.1.2.3 someOTHERblockedhostname
望まない限り、ブロックされた各ホスト名は同じIPを使用することをブロックしますできます。区別)
その後、ブロックするIPを使用できますiptables

ただし、DNSリゾルバー(例:Next DNSまたは1.1.1.30.0.0.0)がブロックされたホスト名(代わりに)を返すNXDOMAINと、これを行うことはできません(もちろん、各ホストが/ etc / hostsに優先するため、手動で追加したい場合は除外 - で行を/etc/hosts変更しないとします)。hosts: files dns/etc/nsswitch.conf


古い:(編集したけど)

Linux(最新のGentooとPop OS!を使ってみました)で次の行がある場合/etc/hosts

0.0.0.0 somehosthere

次に、ルートとして実行し(ポート443で受信したローカルホストサーバーをシミュレートするため)、
# nc -l -p 443 -s 127.0.0.1
ブラウザに移動し(FirefoxとChrome / Chromiumでテスト)、アドレスバーに入力し
https://somehosthere
ます
0.0.0.0:443

https://0.0.0.0

その後、起動した端末nc(別名netcat)に接続試行が表示されます(somehosthereURLで使用している場合はプレーンテキストを含むいくつかのゴミテキスト)。

または、ブラウザの代わりに次のことを試すこともできます。
curl https://somehosthere
または、プレーンテキストリクエストを表示するには:
curl http://somehosthere:443

長い間使用してdnsmasqも軽減されないようですが、DNSリゾルバ(NextDNSや0.0.0.0 somehosthere/etc/hostsdnsmasqクラウドフレア1.1.1.3)は(0.0.0.0代わりに返されます。 )NXDOMAIN本物この記事を書いている時点で、そのホスト名があなたのホスト名/etc/hosts(およびあなたが使用dnsmasqするように指示した/etc/hostsホスト名)にない場合は、これを軽減する2つの方法があります(どちらか一方または両方が機能します)。

  1. dnsmasqパラメータの使用--stop-dns-rebind
       --stop-dns-rebind
              Reject (and log) addresses from upstream nameservers which are in
              the private ranges. This blocks an attack where a browser  behind
              a  firewall  is  used to probe machines on the local network. For
              IPv6, the private range covers the IPv4-mapped addresses in  pri‐
              vate  space  plus  all  link-local  (LL) and site-local (ULA) ad‐
              dresses.
  1. この行を使用すると、解決されたホスト名は何でも自動的にbogus-nxdomain=0.0.0.0返さ/etc/dnsmasq.confdnsmasqます(そのホスト名が/ etc / hostsに戻っている場合(dnsmasqバイパス)、そうでなければdnsmasqに使用するように指示されていない場合)。NXDOMAIN0.0.0.0/etc/hosts

だから質問の2番目の部分は0.0.0.0へのアクセスが127.0.0.1にリダイレクトされるのを防ぐ方法は?NextDNSを使用する場合(または1.1.1.3 クラウドフレア)DNSリゾルバとして0.0.0.0NXDOMAINの代わりにブロックされたホスト名を返すので、Webページをロードすると、Webページの一部(ブロックされたホスト名にあります)がポート443(存在する場合)で実行されているローカルホストサーバーにアクセスしようとします。になります。単にブロックされるのではなく、ページをブロックするだけです。

これを知っている関連ブラウザ固有の公開問題(0.0.0.0は127.0.0.1にマッピングされています):
Chrome / Chromium:https://bugs.chromium.org/p/chromium/issues/detail?id=1300021 Firefoxブラウザ:https://bugzilla.mozilla.org/show_bug.cgi?id=1672528#c17

ベストアンサー1

なぜこれが起こるのかについての説明は次のとおりです。IP 0.0.0.0に正常に接続されました。どのように?なぜ?- 簡単に言うと、宛先アドレス(0.0.0.0)を持たないパケットは送信元アドレスが宛先アドレスにコピーされ、送信元または宛先がないパケットは送信元アドレスと宛先アドレスがループバックアドレス(INADDR_LOOPBACK、127.0.0.1)生成されたデータパケットはループバックインターフェイスを介して送信されます。

ご覧のとおり、この動作はLinuxカーネルのIPv4ネットワークスタックにハードコードされている、これを変更する唯一の方法はカーネルをパッチすることです。

diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 795cbe1de912..df15a685f04c 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2740,14 +2740,8 @@ struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4,
        }
 
        if (!fl4->daddr) {
-               fl4->daddr = fl4->saddr;
-               if (!fl4->daddr)
-                       fl4->daddr = fl4->saddr = htonl(INADDR_LOOPBACK);
-               dev_out = net->loopback_dev;
-               fl4->flowi4_oif = LOOPBACK_IFINDEX;
-               res->type = RTN_LOCAL;
-               flags |= RTCF_LOCAL;
-               goto make_route;
+               rth = ERR_PTR(-ENETUNREACH);
+               goto out;
        }
 
        err = fib_lookup(net, fl4, res, 0);

このパッチは上記の「なぜ?」部分を説明する元の実装を示します。パケットに宛先アドレスがない場合(つまり0.0.0.0):

  • 送信元アドレスが宛先アドレスにコピーされます。
  • パケットの場合まだ宛先住所がありません。つまりまた、ソースアドレスはなく、両方のアドレスはループバックアドレス(127.0.0.1)に設定されています。
  • すべての場合において、発信装置はループバック装置として設定され、それに応じて経路が構成される。

パッチは、代わりに「Network Unreachable」エラーを返すようにこの動作を変更します。

おすすめ記事