Я должен сделать http-запросы через VPN. Есть PHP-код, использующий cURL, делающий то, что мне нужно, ничего дополнительного:
curl_setopt($cu, CURLOPT_INTERFACE, "tun0");
Этот интерфейс из ifconfig:
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500
inet 10.13.13.2 netmask 255.255.255.255 destination 10.13.13.1
inet6 fe80::80ee:132:d102:a52d prefixlen 64 scopeid 0x20<link>
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 100 (UNSPEC)
Мой код go (как я понимаю, я должен привязаться к ip tun0):
package main
import (
"io/ioutil"
"log"
"net"
"net/http"
"time"
)
func main() {
httpTransport := &http.Transport{}
ief, err := net.InterfaceByName("tun0")
if err != nil {
log.Fatal(err)
}
addrs, err := ief.Addrs()
if err != nil {
log.Fatal(err)
}
tcpAddr := &net.TCPAddr{IP: addrs[0].(*net.IPNet).IP}
println(tcpAddr.String())
httpTransport.Dial = (&net.Dialer{
Timeout: 20 * time.Second,
LocalAddr: tcpAddr,
}).Dial
c := &http.Client{
Transport: httpTransport,
Timeout: 30 * time.Second,
}
req, err := http.NewRequest(
http.MethodGet,
"http://example.com/",
nil,
)
if err != nil {
log.Fatal(err)
}
resp, err := c.Do(req)
if err != nil {
log.Fatal(err)
}
bytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
println(string(bytes))
}
Итак, что я получаю:
10.13.13.2:0
2019/03/21 15:29:42 Get http://example.com/: dial tcp 10.13.13.2:0->93.184.216.34:80: i/o timeout
exit status 1
Php-код cUrl быстро открывает эту страницу. Я много раз пробовал с кодом Go, поэтому таймауты ничего не могут сделать. Любые идеи, как заменить эту одну строку PHP в Go?
UPDATE
PHP-код получает ту же страницу через tun0 и выводит:
<?php
$cu = curl_init();
curl_setopt($cu, CURLOPT_URL, "http://example.com");
curl_setopt($cu, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($cu, CURLOPT_CONNECTTIMEOUT, 20);
curl_setopt($cu, CURLOPT_TIMEOUT, 30);
curl_setopt($cu, CURLOPT_INTERFACE, "tun0");
$result = curl_exec($cu);;
curl_close($cu);
echo $result . PHP_EOL;
Выход:
<!doctype html>
<html>
<head>
<title>Example Domain</title>
<meta charset="utf-8" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css">
body {
background-color: #f0f0f2;
margin: 0;
padding: 0;
font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
div {
width: 600px;
margin: 5em auto;
padding: 50px;
background-color: #fff;
border-radius: 1em;
}
a:link, a:visited {
color: #38488f;
text-decoration: none;
}
@media (max-width: 700px) {
body {
background-color: #fff;
}
div {
width: auto;
margin: 0 auto;
border-radius: 0;
padding: 1em;
}
}
</style>
</head>
<body>
<div>
<h1>Example Domain</h1>
<p>This domain is established to be used for illustrative examples in documents. You may use this
domain in examples without prior coordination or asking for permission.</p>
<p><a href="http://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>