1. ホーム
  2. http

[解決済み] http.RequestからクライアントのIPアドレスを取得する正しい方法

2023-01-18 16:34:45

質問

からすべてのクライアントの IP アドレスを取得する正しい方法は何ですか? http.Request ? では PHP には、たくさんの 変数があります。 をチェックする必要があります。Goでも同じなのでしょうか?

私が見つけたのは

req.RemoteAddr

また、リクエストの大文字と小文字は区別されますか? 例えば x-forwarded-for と同じです。 X-Forwarded-ForX-FORWARDED-FOR ? から req.Header.Get("X-FORWARDED-FOR") )

どのように解決するのですか?

を見てみると http.リクエスト を見ると、以下のようなメンバ変数があることがわかります。

// HTTP defines that header names are case-insensitive.
// The request parser implements this by canonicalizing the
// name, making the first character and any characters
// following a hyphen uppercase and the rest lowercase.
//
// For client requests certain headers are automatically
// added and may override values in Header.
//
// See the documentation for the Request.Write method.
Header Header

// RemoteAddr allows HTTP servers and other software to record
// the network address that sent the request, usually for
// logging. This field is not filled in by ReadRequest and
// has no defined format. The HTTP server in this package
// sets RemoteAddr to an "IP:port" address before invoking a
// handler.
// This field is ignored by the HTTP client.
RemoteAddr string

を使うことができます。 RemoteAddr を使ってリモートクライアントの IP アドレスとポート (フォーマットは "IP:port") を取得し、これは元のリクエスト元のアドレスである または最後のプロキシ (例えば、サーバの前にあるロードバランサ) のアドレスです。

確かにこれだけです。

次にヘッダを調査すると 大文字小文字を区別しない (上記のドキュメントによる) であり、すべての例が動作し、同じ結果をもたらすことを意味します。

req.Header.Get("X-Forwarded-For") // capitalisation
req.Header.Get("x-forwarded-for") // doesn't
req.Header.Get("X-FORWARDED-FOR") // matter

これは、内部的に http.Header.Get がキーを正規化するからです。(もしあなたがヘッダーマップに直接アクセスしたいのであれば、 を通さずに Get を通してではなく、直接ヘッダーマップにアクセスしたい場合は http.CanonicalHeaderKey を最初に使う必要があります)。

最後に "X-Forwarded-For" は、おそらくクライアントの IP に関するより多くの情報を取得するために見てみたいフィールドでしょう。クライアントが望めばそこに何でも入れることができるので、これはリモート側で使用されている HTTP ソフトウェアに大きく依存します。また 期待される 形式 は、IP アドレスのカンマ+スペース区切りリストです。たとえば、選択した単一の IP (おそらくリストの最初のもの) を取得するために、それを少し解析する必要があります。

// Assuming format is as expected
ips := strings.Split("10.0.0.1, 10.0.0.2, 10.0.0.3", ", ")
for _, ip := range ips {
    fmt.Println(ip)
}

が生成されます。

10.0.0.1
10.0.0.2
10.0.0.3