check thing
This commit is contained in:
@ -45,10 +45,9 @@ Features: Done
|
||||
* CONNECT support
|
||||
* "New Ident" signaling interface(Unix-only for now)(I guess I might have done
|
||||
for Windows too now but I haven't tried it out yet).
|
||||
* Outproxy Support
|
||||
|
||||
Features: Planned
|
||||
-----------------
|
||||
|
||||
* Outproxy Support
|
||||
* Traffic Shaping
|
||||
* Authentication
|
||||
|
11
go.mod
11
go.mod
@ -3,8 +3,17 @@ module github.com/eyedeekay/httptunnel
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
crawshaw.io/littleboss v0.0.0-20190317185602-8957d0aedcce // indirect
|
||||
github.com/d5/tengo v1.24.3 // indirect
|
||||
github.com/eyedeekay/goSam v0.1.1-0.20190814204230-d4c9b8c57dd6
|
||||
github.com/eyedeekay/sam-forwarder v0.0.0-20190831205522-ccc29b5e6647
|
||||
github.com/eyedeekay/sam-forwarder v0.0.0-20190908210105-71ca8cd65fda
|
||||
github.com/eyedeekay/sam3 v0.0.0-20190730185140-f8d54526ea25
|
||||
github.com/mwitkow/go-http-dialer v0.0.0-20161116154839-378f744fb2b8
|
||||
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2
|
||||
gitlab.com/golang-commonmark/html v0.0.0-20180917080848-cfaf75183c4a // indirect
|
||||
gitlab.com/golang-commonmark/linkify v0.0.0-20180917065525-c22b7bdb1179 // indirect
|
||||
gitlab.com/golang-commonmark/mdurl v0.0.0-20180912090424-e5bce34c34f2 // indirect
|
||||
gitlab.com/golang-commonmark/puny v0.0.0-20180912090636-2cd490539afe // indirect
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
|
||||
)
|
||||
|
@ -24,7 +24,7 @@ var (
|
||||
samPortString = flag.String("bridge-port", "7656", ":port of the SAM bridge")
|
||||
watchProfiles = flag.String("watch-profiles", "~/.mozilla/.firefox.profile.i2p.default/user.js,~/.mozilla/.firefox.profile.i2p.debug/user.js", "Monitor and control these Firefox profiles")
|
||||
destfile = flag.String("dest-file", "invalid.tunkey", "Use a long-term destination key")
|
||||
debugConnection = flag.Bool("conn-debug", true, "Print connection debug info")
|
||||
debugConnection = flag.Bool("conn-debug", false, "Print connection debug info")
|
||||
inboundTunnelLength = flag.Int("in-tun-length", 2, "Tunnel Length(default 3)")
|
||||
outboundTunnelLength = flag.Int("out-tun-length", 2, "Tunnel Length(default 3)")
|
||||
inboundTunnels = flag.Int("in-tunnels", 2, "Inbound Tunnel Count(default 2)")
|
||||
@ -43,8 +43,10 @@ var (
|
||||
reduceIdleQuantity = flag.Int("reduce-idle-tunnels", 1, "Reduce tunnels to this level")
|
||||
runCommand = flag.String("run-command", "", "Execute command using the *_PROXY environment variables")
|
||||
runArguments = flag.String("run-arguments", "", "Pass arguments to run-command")
|
||||
suppressLifetime = flag.Bool("suppress-lifetime-output", false, "Suppress \"Tunnel lifetime\" output")
|
||||
suppressLifetime = flag.Bool("suppress-lifetime-output", true, "Suppress \"Tunnel lifetime\" output")
|
||||
runQuiet = flag.Bool("run-quiet", false, "Suppress all non-command output")
|
||||
outproxy = flag.String("outproxy-addr", "false.i2p", "Use this address as an outproxy, either a base32 address or a local HTTP proxy")
|
||||
socks = flag.Bool("outproxy-socks", true, "Use a SOCKS outproxy")
|
||||
)
|
||||
|
||||
var addr string
|
||||
@ -86,6 +88,8 @@ func proxyMain(ctx context.Context, ln net.Listener, cln net.Listener) {
|
||||
SetPort(*samPortString),
|
||||
SetProxyAddr(ln.Addr().String()),
|
||||
SetControlAddr(cln.Addr().String()),
|
||||
SetOutProxy(*outproxy),
|
||||
SetOutProxySocks(*socks),
|
||||
SetDebug(*debugConnection),
|
||||
SetInLength(uint(*inboundTunnelLength)),
|
||||
SetOutLength(uint(*outboundTunnelLength)),
|
||||
|
@ -160,6 +160,26 @@ func SetProxyHost(s string) func(*SAMHTTPProxy) error {
|
||||
}
|
||||
}
|
||||
|
||||
//SetOutProxy sets the host of the client's outproxy, it may be a base32 or a local proxy
|
||||
func SetOutProxy(s string) func(*SAMHTTPProxy) error {
|
||||
return func(c *SAMHTTPProxy) error {
|
||||
c.UseOutProxy = s
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
//SetOutProxySocks tells it to use a SOCKS outproxy instead of HTTP
|
||||
func SetOutProxySocks(s bool) func(*SAMHTTPProxy) error {
|
||||
return func(c *SAMHTTPProxy) error {
|
||||
if s {
|
||||
c.outproxytype = "socks://"
|
||||
return nil
|
||||
}
|
||||
c.outproxytype = "http://"
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
//SetProxyPort sets the host of the client's Proxy controller
|
||||
func SetProxyPort(s string) func(*SAMHTTPProxy) error {
|
||||
return func(c *SAMHTTPProxy) error {
|
||||
|
199
httptunnel.go
199
httptunnel.go
@ -3,12 +3,14 @@ package i2phttpproxy
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"golang.org/x/net/proxy"
|
||||
"golang.org/x/time/rate"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -23,17 +25,24 @@ import (
|
||||
"github.com/eyedeekay/sam-forwarder/hashhash"
|
||||
"github.com/eyedeekay/sam-forwarder/i2pkeys"
|
||||
"github.com/eyedeekay/sam-forwarder/interface"
|
||||
"github.com/eyedeekay/sam-forwarder/tcp"
|
||||
"github.com/eyedeekay/sam3/i2pkeys"
|
||||
"github.com/mwitkow/go-http-dialer"
|
||||
"github.com/phayes/freeport"
|
||||
)
|
||||
|
||||
type SAMHTTPProxy struct {
|
||||
goSam *goSam.Client
|
||||
Hasher *hashhash.Hasher
|
||||
client *http.Client
|
||||
transport *http.Transport
|
||||
rateLimiter *rate.Limiter
|
||||
goSam *goSam.Client
|
||||
Hasher *hashhash.Hasher
|
||||
client *http.Client
|
||||
outproxyclient *http.Client
|
||||
transport *http.Transport
|
||||
rateLimiter *rate.Limiter
|
||||
outproxy *samforwarder.SAMClientForwarder
|
||||
outproxydialer proxy.Dialer
|
||||
outproxytype string
|
||||
|
||||
useOutProxy bool
|
||||
UseOutProxy string
|
||||
|
||||
dialed bool
|
||||
debug bool
|
||||
@ -190,20 +199,21 @@ func (p *SAMHTTPProxy) samaddr() string {
|
||||
func (p *SAMHTTPProxy) ServeHTTP(wr http.ResponseWriter, req *http.Request) {
|
||||
plog(req.RemoteAddr, " ", req.Method, " ", req.URL)
|
||||
p.Save()
|
||||
if req.URL.Scheme != "http" && req.URL.Scheme != "https" {
|
||||
/*if req.URL.Scheme != "http" && req.URL.Scheme != "https" {
|
||||
if !(req.Method == http.MethodConnect) {
|
||||
msg := "Unsupported protocol scheme " + req.URL.Scheme
|
||||
http.Error(wr, msg, http.StatusBadRequest)
|
||||
plog(msg)
|
||||
return
|
||||
}
|
||||
}*/
|
||||
|
||||
if req.URL.Host == p.Conf.ControlHost+":"+p.Conf.ControlPort {
|
||||
p.reset(wr, req)
|
||||
return
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(req.URL.Host, ".i2p") {
|
||||
if req.URL.Host == p.Conf.ControlHost+":"+p.Conf.ControlPort {
|
||||
p.reset(wr, req)
|
||||
return
|
||||
}
|
||||
if !strings.HasSuffix(req.URL.Host, ".i2p") && p.UseOutProxy == "" {
|
||||
msg := "Unsupported host " + req.URL.Host
|
||||
if !Quiet {
|
||||
http.Error(wr, msg, http.StatusBadRequest)
|
||||
@ -216,6 +226,13 @@ func (p *SAMHTTPProxy) ServeHTTP(wr http.ResponseWriter, req *http.Request) {
|
||||
p.get(wr, req)
|
||||
return
|
||||
} else {
|
||||
if !strings.HasSuffix(req.URL.Host, ".i2p") && p.UseOutProxy != "" {
|
||||
p.outproxyget(wr, req)
|
||||
return
|
||||
} else {
|
||||
plog("No outproxy configured ", p.UseOutProxy, p.outproxy.Target())
|
||||
return
|
||||
}
|
||||
p.connect(wr, req)
|
||||
return
|
||||
}
|
||||
@ -265,10 +282,35 @@ func (p *SAMHTTPProxy) reset(wr http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *SAMHTTPProxy) outproxyget(wr http.ResponseWriter, req *http.Request) {
|
||||
plog("CONNECT via outproxy to", req.URL.Host)
|
||||
dest_conn, err := p.outproxydialer.Dial("tcp", req.URL.String())
|
||||
if err != nil {
|
||||
if !Quiet {
|
||||
plog(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
hijacker, ok := wr.(http.Hijacker)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
client_conn, _, err := hijacker.Hijack()
|
||||
if err != nil {
|
||||
if !Quiet {
|
||||
plog(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
go proxycommon.Transfer(dest_conn, client_conn)
|
||||
go proxycommon.Transfer(client_conn, dest_conn)
|
||||
}
|
||||
|
||||
func (p *SAMHTTPProxy) get(wr http.ResponseWriter, req *http.Request) {
|
||||
req.RequestURI = ""
|
||||
proxycommon.DelHopHeaders(req.Header)
|
||||
p.client = p.freshClient()
|
||||
plog("Getting i2p page")
|
||||
//p.client = p.freshClient()
|
||||
resp, err := p.client.Do(req)
|
||||
if err != nil {
|
||||
msg := "Proxy Error " + err.Error()
|
||||
@ -333,6 +375,13 @@ func (p *SAMHTTPProxy) Save() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (p *SAMHTTPProxy) GuaranteePrefix(str string) string {
|
||||
if strings.HasPrefix(p.outproxytype, str) {
|
||||
return str
|
||||
}
|
||||
return p.outproxytype + str
|
||||
}
|
||||
|
||||
func (handler *SAMHTTPProxy) Load() (samtunnel.SAMTunnel, error) {
|
||||
var err error
|
||||
handler.Conf.ClientDest = handler.Save()
|
||||
@ -360,6 +409,128 @@ func (handler *SAMHTTPProxy) Load() (samtunnel.SAMTunnel, error) {
|
||||
}
|
||||
handler.transport = handler.freshTransport()
|
||||
handler.client = handler.freshClient()
|
||||
if handler.UseOutProxy != "" {
|
||||
if strings.HasSuffix(handler.UseOutProxy, ".i2p") {
|
||||
plog("Configuring an outproxy,", handler.UseOutProxy)
|
||||
config := handler.Conf
|
||||
port, err := freeport.GetFreePort()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.TargetPort = strconv.Itoa(port)
|
||||
config.TunName = handler.Conf.TunName + "-outproxy"
|
||||
config.ClientDest = handler.UseOutProxy
|
||||
handler.outproxy, err = samforwarder.NewSAMClientForwarderFromOptions(
|
||||
samforwarder.SetClientSaveFile(config.SaveFile),
|
||||
samforwarder.SetClientFilePath(config.SaveDirectory),
|
||||
samforwarder.SetClientHost(config.TargetHost),
|
||||
samforwarder.SetClientPort(config.TargetPort),
|
||||
samforwarder.SetClientSAMHost(config.SamHost),
|
||||
samforwarder.SetClientSAMPort(config.SamPort),
|
||||
samforwarder.SetClientSigType(config.SigType),
|
||||
samforwarder.SetClientName(config.TunName),
|
||||
samforwarder.SetClientInLength(config.InLength),
|
||||
samforwarder.SetClientOutLength(config.OutLength),
|
||||
samforwarder.SetClientInVariance(config.InVariance),
|
||||
samforwarder.SetClientOutVariance(config.OutVariance),
|
||||
samforwarder.SetClientInQuantity(config.InQuantity),
|
||||
samforwarder.SetClientOutQuantity(config.OutQuantity),
|
||||
samforwarder.SetClientInBackups(config.InBackupQuantity),
|
||||
samforwarder.SetClientOutBackups(config.OutBackupQuantity),
|
||||
samforwarder.SetClientEncrypt(config.EncryptLeaseSet),
|
||||
samforwarder.SetClientLeaseSetKey(config.LeaseSetKey),
|
||||
samforwarder.SetClientLeaseSetPrivateKey(config.LeaseSetPrivateKey),
|
||||
samforwarder.SetClientLeaseSetPrivateSigningKey(config.LeaseSetPrivateSigningKey),
|
||||
samforwarder.SetClientAllowZeroIn(config.InAllowZeroHop),
|
||||
samforwarder.SetClientAllowZeroOut(config.OutAllowZeroHop),
|
||||
samforwarder.SetClientFastRecieve(config.FastRecieve),
|
||||
samforwarder.SetClientCompress(config.UseCompression),
|
||||
samforwarder.SetClientReduceIdle(config.ReduceIdle),
|
||||
samforwarder.SetClientReduceIdleTimeMs(config.ReduceIdleTime),
|
||||
samforwarder.SetClientReduceIdleQuantity(config.ReduceIdleQuantity),
|
||||
samforwarder.SetClientCloseIdle(config.CloseIdle),
|
||||
samforwarder.SetClientCloseIdleTimeMs(config.CloseIdleTime),
|
||||
samforwarder.SetClientAccessListType(config.AccessListType),
|
||||
samforwarder.SetClientAccessList(config.AccessList),
|
||||
samforwarder.SetClientMessageReliability(config.MessageReliability),
|
||||
samforwarder.SetClientPassword(config.KeyFilePath),
|
||||
samforwarder.SetClientDestination(config.ClientDest),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
go handler.outproxy.Serve()
|
||||
if handler.outproxytype == "http://" {
|
||||
proxyURL, err := url.Parse(handler.GuaranteePrefix(handler.outproxy.Target()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
handler.outproxydialer = http_dialer.New(proxyURL, http_dialer.WithTls(&tls.Config{}))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
handler.outproxyclient = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Dial: handler.outproxydialer.Dial,
|
||||
TLSNextProto: make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
|
||||
TLSClientConfig: &tls.Config{},
|
||||
},
|
||||
Timeout: time.Second * 300,
|
||||
CheckRedirect: nil,
|
||||
}
|
||||
} else {
|
||||
handler.outproxydialer, err = proxy.SOCKS5("tcp", handler.outproxy.Target(), nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
handler.outproxyclient = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Dial: handler.outproxydialer.Dial,
|
||||
TLSNextProto: make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
|
||||
TLSClientConfig: &tls.Config{},
|
||||
},
|
||||
Timeout: time.Second * 300,
|
||||
CheckRedirect: nil,
|
||||
}
|
||||
}
|
||||
plog("setup outproxy on", handler.outproxy.Target())
|
||||
} else {
|
||||
if handler.outproxytype == "http://" {
|
||||
proxyURL, err := url.Parse(handler.GuaranteePrefix(handler.UseOutProxy))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
handler.outproxydialer = http_dialer.New(proxyURL, http_dialer.WithTls(&tls.Config{}))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
handler.outproxyclient = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Dial: handler.outproxydialer.Dial,
|
||||
TLSNextProto: make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
|
||||
TLSClientConfig: &tls.Config{},
|
||||
},
|
||||
Timeout: time.Second * 300,
|
||||
CheckRedirect: nil,
|
||||
}
|
||||
} else {
|
||||
handler.outproxydialer, err = proxy.SOCKS5("tcp", handler.UseOutProxy, nil, proxy.Direct)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
handler.outproxyclient = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Dial: handler.outproxydialer.Dial,
|
||||
TLSNextProto: make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
|
||||
TLSClientConfig: &tls.Config{},
|
||||
},
|
||||
Timeout: time.Second * 300,
|
||||
CheckRedirect: nil,
|
||||
}
|
||||
}
|
||||
plog("setup outproxy on", handler.GuaranteePrefix(handler.UseOutProxy))
|
||||
}
|
||||
}
|
||||
handler.Hasher, err = hashhash.NewHasher(len(strings.Replace(handler.Base32(), ".b32.i2p", "", 1)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -375,6 +546,8 @@ func NewHttpProxy(opts ...func(*SAMHTTPProxy) error) (*SAMHTTPProxy, error) {
|
||||
handler.Conf.SamPort = "7656"
|
||||
handler.Conf.ControlHost = "127.0.0.1"
|
||||
handler.Conf.ControlPort = "7951"
|
||||
handler.UseOutProxy = ""
|
||||
handler.outproxytype = "http://"
|
||||
for _, o := range opts {
|
||||
if err := o(&handler); err != nil {
|
||||
return nil, err
|
||||
|
@ -28,3 +28,16 @@ It also has an aggressive mode, which creates a whole new tunnel pool for every
|
||||
single eepSite you visit, by domain(which means that if you visit both the
|
||||
base32 and readable domain, it will create *two* destinations). I advise against
|
||||
using it.
|
||||
|
||||
Features: Done
|
||||
--------------
|
||||
|
||||
* Self-supervising, Self-restarting on Unixes
|
||||
* CONNECT support
|
||||
* "New Ident" signaling interface
|
||||
|
||||
Features: Planned
|
||||
-----------------
|
||||
|
||||
* Outproxy Support
|
||||
* Traffic Shaping
|
||||
|
Reference in New Issue
Block a user