|
package main |
|
|
|
import ( |
|
"context" |
|
"crypto/tls" |
|
"io/ioutil" |
|
"log" |
|
"net" |
|
"net/http" |
|
"os" |
|
"time" |
|
|
|
proxyproto "github.com/pires/go-proxyproto" |
|
) |
|
|
|
func proxyDialer(useTLS bool) func(context.Context, string, string) (net.Conn, error) { |
|
return func(ctx context.Context, network, addr string) (net.Conn, error) { |
|
conn, err := new(net.Dialer).DialContext(ctx, network, addr) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
header := &proxyproto.Header{ |
|
Version: 2, |
|
Command: proxyproto.PROXY, |
|
TransportProtocol: proxyproto.TCPv4, |
|
SourceAddr: &net.TCPAddr{ |
|
IP: net.ParseIP("1.1.1.1"), |
|
Port: 11111, |
|
}, |
|
DestinationAddr: &net.TCPAddr{ |
|
IP: net.ParseIP("2.2.2.2"), |
|
Port: 22222, |
|
}, |
|
} |
|
|
|
// Both curl and Nginx appear to agree on the header occuring before the |
|
// TLS handshake. |
|
_, err = header.WriteTo(conn) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
if !useTLS { |
|
return conn, nil |
|
} |
|
config := &tls.Config{InsecureSkipVerify: true} |
|
tlsConn := tls.Client(conn, config) |
|
return tlsConn, nil |
|
} |
|
} |
|
|
|
func ignoreRedirects(*http.Request, []*http.Request) error { |
|
return http.ErrUseLastResponse |
|
} |
|
|
|
func proxyClient(spoofedIP string) *http.Client { |
|
return &http.Client{ |
|
Timeout: time.Second, |
|
Transport: &http.Transport{ |
|
DialContext: proxyDialer(false), |
|
DialTLSContext: proxyDialer(true), |
|
}, |
|
CheckRedirect: ignoreRedirects, |
|
} |
|
} |
|
|
|
func main() { |
|
req, err := http.NewRequest("GET", os.Args[1], nil) |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
|
|
client := proxyClient() |
|
resp, err := client.Do(req) |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
|
|
defer resp.Body.Close() |
|
log.Printf("%+v\n", resp) |
|
|
|
body, err := ioutil.ReadAll(resp.Body) |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
log.Printf("%s\n", body) |
|
} |