net.SplitHostPort(r.RemoteAddr) go 中的安全性

问题描述 投票:0回答:2

我的服务器依靠 IP 过滤来确保安全。我想知道是否有人可以使用

net.SplitHostPort(r.RemoteAddr) 

绕过依赖于远程 IP 过滤的保护

为此,我创建了这个虚拟 http 服务器:

package main

import (
    "fmt"
    "net"
    "net/http"
)

func getHello(w http.ResponseWriter, r *http.Request) {
    fmt.Printf("got /hello request\n")
    host, _, _ := net.SplitHostPort(r.RemoteAddr)
    fmt.Printf("Ip is %s\n", host)
}

func main() {
    http.HandleFunc("/hello", getHello)

    http.ListenAndServe(":3333", nil)
}

然后我用curl做了一些测试:

curl http://localhost:3333/hello 
<- Logs in my server -> Ip is 127.0.0.1

curl http://localhost:3333/hello -H "X-Forwarded-For: 3.3.3.3" -H "Host: 3.3.3.3"
<- Logs in my server -> Ip is 127.0.0.1

这似乎很安全,因为我无法欺骗我的服务器认为请求的 IP 是

3.3.3.3

r.RemoteAddr
真的安全并在TCP数据包中查找IP吗?或者有没有办法通过使用标头或伪造数据包来绕过它?

go ip
2个回答
0
投票

期望通过设置 HTTP 标头来更改远程地址表明了对 TCP/IP 堆栈如何工作的根本误解。没关系 - 这只是让问题变得难以回答。

http.Request.RemoteAddr
由 IP 数据包的标头字段填充:“源 ip 地址”

虽然可以在此标头字段中制作具有任意值的数据包,但建立 TCP 会话需要三向握手。如果服务器尝试回复没有匹配的

active-open
会话的主机,它将被拒绝。

这似乎很安全,因为我无法欺骗我的服务器认为请求的 IP 是 3.3.3.3。

据您所知,您设置的两个标头是众所周知的。

  1. Host
    是必需的,用于指定您打算将请求发送到哪个 serversource

  2. X-Forwarded-For
    是代理的通用标头:source

虽然后者(如果存在)可用于了解原始客户端的 IP 地址……它仍然是一个标头。由应用程序来解释它。


0
投票

根据文档这里

RemoteAddr 字段被 HTTP 客户端忽略。

仅由 HTTP 服务器通过读取

Source Address
数据包中的
IP
来设置。

Host
X-Forwarded-For
http
标头,仅在 TCP 握手后传递。因此,在成功握手后,在标头中传递此类信息之前,您的 HTTP 服务器已经获得了
RemoteAddr

© www.soinside.com 2019 - 2024. All rights reserved.