56 lines
1.2 KiB
Go
Executable File
56 lines
1.2 KiB
Go
Executable File
package guard
|
|
|
|
import (
|
|
"net"
|
|
"net/http"
|
|
"net/netip"
|
|
"syscall"
|
|
"time"
|
|
)
|
|
|
|
func (policy *Policy) NewHTTPClient() *http.Client {
|
|
dialer := &net.Dialer{
|
|
Timeout: 15 * time.Second,
|
|
KeepAlive: 30 * time.Second,
|
|
Control: policy.controlConnection,
|
|
}
|
|
|
|
transport := &http.Transport{
|
|
Proxy: nil,
|
|
DialContext: dialer.DialContext,
|
|
ForceAttemptHTTP2: true,
|
|
TLSHandshakeTimeout: 15 * time.Second,
|
|
ResponseHeaderTimeout: 30 * time.Second,
|
|
ExpectContinueTimeout: time.Second,
|
|
MaxIdleConns: 10,
|
|
IdleConnTimeout: 90 * time.Second,
|
|
}
|
|
|
|
return &http.Client{
|
|
Transport: transport,
|
|
CheckRedirect: policy.checkRedirect,
|
|
}
|
|
}
|
|
|
|
func (policy *Policy) controlConnection(_ string, address string, _ syscall.RawConn) error {
|
|
addressPort, err := netip.ParseAddrPort(address)
|
|
if err != nil {
|
|
return ErrBlockedAddress
|
|
}
|
|
if !IsPublicAddress(addressPort.Addr()) {
|
|
return ErrBlockedAddress
|
|
}
|
|
if !policy.portAllowed(addressPort.Port()) {
|
|
return ErrBlockedPort
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (policy *Policy) checkRedirect(request *http.Request, previous []*http.Request) error {
|
|
if len(previous) >= maxRedirects {
|
|
return ErrTooManyRedirects
|
|
}
|
|
_, err := policy.ValidateURL(request.URL.String())
|
|
return err
|
|
}
|