Golang如何强制HTTP请求到特定的IP地址(类似于curl的–resolve参数)

huangapple go评论81阅读模式
英文:

golang force http request to specific ip (similar to curl --resolve)

问题

如何强制使用特定的IP地址进行golang的https get请求?我想跳过DNS解析并自己提供IP地址。在curl中,相当于使用--resolve参数,示例如下:

curl https://domain.com/dir/filename --resolve "domain.com:443:10.10.10.10"

由于这是SSL连接,我想避免在URL中替换域名为IP地址,示例如下:

curl https://10.10.10.10/dir/filename --header "Host: domain.com"

英文:

How can I force a golang https get request to use a specific IP address. I want to skip DNS resolution and provide the IP myself. The equivalent in curl would be a --resolve as illustrated below.

curl https://domain.com/dir/filename --resolve "domain.com:443:10.10.10.10"

Since this is ssl I want to avoid substituting in the IP for the domain as in the following example.

curl https://10.10.10.10/dir/filename --header "Host: domain.com"

答案1

得分: 35

你可以提供一个自定义的Transport.DialContext函数。

func main() {
    dialer := &net.Dialer{
        Timeout:   30 * time.Second,
        KeepAlive: 30 * time.Second,
        // DualStack: true, // this is deprecated as of go 1.16
    }
    // or create your own transport, there's an example on godoc.
    http.DefaultTransport.(*http.Transport).DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
        if addr == "google.com:443" {
            addr = "216.58.198.206:443"
        }
        return dialer.DialContext(ctx, network, addr)
    }
    resp, err := http.Get("https://google.com")
    log.Println(resp.Header, err)
}
英文:

You can provide a custom Transport.DialContext function.

func main() {
	dialer := &net.Dialer{
		Timeout:   30 * time.Second,
		KeepAlive: 30 * time.Second,
		// DualStack: true, // this is deprecated as of go 1.16
	}
    // or create your own transport, there's an example on godoc.
	http.DefaultTransport.(*http.Transport).DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
		if addr == "google.com:443" {
			addr = "216.58.198.206:443"
		}
		return dialer.DialContext(ctx, network, addr)
	}
	resp, err := http.Get("https://google.com")
	log.Println(resp.Header, err)
}

答案2

得分: 5

OneOfOne的回答非常好。我在这里发布完整的工作包代码,以便像我这样的新手更容易理解。我添加了一些println语句,这样你就可以在修改前后看到addr的值。

package main

import (
	"context"
	"fmt"
	"log"
	"net"
	"net/http"
	"time"
)

func main() {
	dialer := &net.Dialer{
		Timeout:   30 * time.Second,
		KeepAlive: 30 * time.Second,
		DualStack: true,
	}
	// or create your own transport, there's an example on godoc.
	http.DefaultTransport.(*http.Transport).DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
		fmt.Println("原始地址 =", addr)
		if addr == "google.com:443" {
			addr = "216.58.198.206:443"
			fmt.Println("修改后的地址 =", addr)
		}
		return dialer.DialContext(ctx, network, addr)
	}
	resp, err := http.Get("https://google.com")
	log.Println(resp.Header, err)
}

希望对你有帮助!

英文:

OneOfOne's answer above is excellent. I am posting the full working package code here to make it easier for noobs like me. I added a couple of println so that you could see the addr value before and after modification.

package main

import (
	"context"
	"fmt"
	"log"
	"net"
	"net/http"
	"time"
)

func main() {
	dialer := &net.Dialer{
		Timeout:   30 * time.Second,
		KeepAlive: 30 * time.Second,
		DualStack: true,
	}
	// or create your own transport, there's an example on godoc.
	http.DefaultTransport.(*http.Transport).DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
		fmt.Println("address original =", addr)
		if addr == "google.com:443" {
			addr = "216.58.198.206:443"
			fmt.Println("address modified =", addr)
		}
		return dialer.DialContext(ctx, network, addr)
	}
	resp, err := http.Get("https://google.com")
	log.Println(resp.Header, err)
}

huangapple
  • 本文由 发表于 2016年11月16日 12:46:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/40624248.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定