diff --git a/Makefile b/Makefile index 093aeb4..b1f2bc6 100644 --- a/Makefile +++ b/Makefile @@ -76,3 +76,6 @@ vet: go vet ./*.go go vet ./httpproxy/*.go go vet ./windows/*.go + +clean: + rm -f httpproxy-* diff --git a/README.md b/README.md index 89d385c..08f0494 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,23 @@ -httptunnel -========== +i2phttpproxy +============ -Super simple standalone http proxy for i2p using SAM. It's mostly just a way of -easily setting up a single-identity for a single application. It offers a single -HTTP Proxy tunnel for a single application and is a form of isolation, but it -isn't Tor-like isolation in that it's intended to be started by the application -and is not based on a SOCKS proxy with extended behavior. It's tiny, it's pure -Go, it's easy to embed in other HTTP applications requiring a client proxy, and -the default executable is self-supervising on Unix-like plaforms. It will work -with any i2p router that has a SAM bridge. +This is a very simple standalone HTTP Proxy for i2p based on the SAM Bridge. It +has a few advantages in certain situations, especially for adapting applications +that speak HTTP to the i2p network. It allows applications to start their own +HTTP proxies, with their own identities within i2p and their own discrete +configurations. It also has some disadvantages, it cannot add new readable +names to your i2p address book nor is it able to use an outproxy. It's new, but +it should be stable enough to experiment with a Tor Browser or a hardened +Firefox configuration. +It is not, and is not intended to be, and will not be intended for use by +multiple clients at the same time. It might be more-or-less OK as part of an +inproxy but you should only use it for one client at a time. A multi-client +solution will also be available soon([eeProxy](https://github.com/eyedeekay/eeProxy). + +Features: Done +-------------- + + * Self-supervising, Self-restarting on Unixes + * CONNECT support + * "New Ident" signaling interface(Unix-only for now) diff --git a/httpcontroller.go b/httpcontroller.go new file mode 100644 index 0000000..23e452a --- /dev/null +++ b/httpcontroller.go @@ -0,0 +1,33 @@ +package i2phttpproxy + +import ( + "log" + "net/http" + "os" + "os/exec" +) + +type SAMHTTPController struct { +} + +func (p *SAMHTTPController) ServeHTTP(wr http.ResponseWriter, req *http.Request) { + err := unixRestart() + if err != nil { + log.Fatal(err) + } + wr.WriteHeader(http.StatusOK) + wr.Write([]byte("200 - Restart OK!")) +} + +func unixRestart() error { + path, err := os.Executable() + if err != nil { + return err + } + cmnd := exec.Command(path, "-littleboss=reload") + err = cmnd.Run() + if err != nil { + return err + } + return nil +} diff --git a/httpproxy/main.go b/httpproxy/main.go index e4fb7ee..8921dbd 100644 --- a/httpproxy/main.go +++ b/httpproxy/main.go @@ -2,39 +2,116 @@ package main import ( "context" + "flag" "log" "net" "net/http" + "time" ) import ( + . "github.com/eyedeekay/httptunnel" "github.com/eyedeekay/littleboss" ) +var ( + tunnelName = flag.String("service-name", "sam-http-proxy", "Name of the service(can be anything)") + samHostString = flag.String("bridge-host", "127.0.0.1", "host: of the SAM bridge") + samPortString = flag.String("bridge-port", "7656", ":port of the SAM bridge") + 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 8)") + outboundTunnels = flag.Int("out-tunnels", 2, "Outbound Tunnel Count(default 8)") + inboundBackups = flag.Int("in-backups", 1, "Inbound Backup Count(default 3)") + outboundBackups = flag.Int("out-backups", 1, "Inbound Backup Count(default 3)") + inboundVariance = flag.Int("in-variance", 0, "Inbound Backup Count(default 3)") + outboundVariance = flag.Int("out-variance", 0, "Inbound Backup Count(default 3)") + dontPublishLease = flag.Bool("no-publish", true, "Don't publish the leaseset(Client mode)") + //encryptLease = flag.Bool("encrypt-lease", true, "Encrypt the leaseset(") + reduceIdle = flag.Bool("reduce-idle", false, "Reduce tunnels on extended idle time") + reduceIdleTime = flag.Int("reduce-idle-time", 2000000, "Reduce tunnels after time(Ms)") + reduceIdleQuantity = flag.Int("reduce-idle-tunnels", 1, "Reduce tunnels to this level") +) + +var addr string + func main() { - lb := littleboss.New("i2p-http-tunnel") - ln := lb.Listener("http", "tcp", "127.0.0.1:7950", "The address of the proxy") + lb := littleboss.New(*tunnelName) + ln := lb.Listener("proxy-addr", "tcp", "127.0.0.1:7950", "The address of the proxy") + cln := lb.Listener("control-addr", "tcp", "127.0.0.1:7951", "The address of the controller") lb.Run(func(ctx context.Context) { - proxyMain(ctx, ln.Listener()) + proxyMain(ctx, ln.Listener(), cln.Listener()) }) } -func proxyMain(ctx context.Context, ln net.Listener) { - handler, err := NewHttpProxy() +func proxyMain(ctx context.Context, ln net.Listener, cln net.Listener) { + flag.Parse() + srv := &http.Server{ + ReadTimeout: 600 * time.Second, + WriteTimeout: 600 * time.Second, + Addr: addr, + } + var err error + srv.Handler, err = NewHttpProxy( + SetHost(*samHostString), + SetPort(*samPortString), + SetDebug(*debugConnection), + SetInLength(uint(*inboundTunnelLength)), + SetOutLength(uint(*outboundTunnelLength)), + SetInQuantity(uint(*inboundTunnels)), + SetOutQuantity(uint(*outboundTunnels)), + SetInBackups(uint(*inboundBackups)), + SetOutBackups(uint(*outboundBackups)), + SetInVariance(*inboundVariance), + SetOutVariance(*outboundVariance), + SetUnpublished(*dontPublishLease), + SetReduceIdle(*reduceIdle), + SetReduceIdleTime(uint(*reduceIdleTime)), + SetReduceIdleQuantity(uint(*reduceIdleQuantity)), + ) if err != nil { log.Fatal(err) } + ctrlsrv := &http.Server{ + ReadTimeout: 600 * time.Second, + WriteTimeout: 600 * time.Second, + Addr: addr, + Handler: &SAMHTTPController{}, + } go func() { - log.Println("Starting proxy server on", ln.Addr()) - if err := http.Serve(ln, handler); err != nil { + log.Println("Starting control server on", cln.Addr()) + if err := ctrlsrv.Serve(cln); err != nil { if err == http.ErrServerClosed { return } log.Fatal("Serve:", err) } + log.Println("Stopping control server on", cln.Addr()) }() - log.Println("Stopping proxy server on", ln.Addr()) + go func() { + log.Println("Starting proxy server on", ln.Addr()) + if err := srv.Serve(ln); err != nil { + if err == http.ErrServerClosed { + return + } + log.Fatal("Serve:", err) + } + log.Println("Stopping proxy server on", ln.Addr()) + }() + + go counter() + <-ctx.Done() } + +func counter() { + var x int + for { + log.Println("Identity is", x, "minute(s) old") + time.Sleep(1 * time.Minute) + x++ + } +} diff --git a/httptunnel-options.go b/httptunnel-options.go new file mode 100644 index 0000000..52bc32e --- /dev/null +++ b/httptunnel-options.go @@ -0,0 +1,315 @@ +package i2phttpproxy + +import ( + "fmt" + "strconv" + "strings" +) + +//Option is a client Option +type Option func(*SAMHTTPProxy) error + +//SetAddr sets a clients's address in the form host:port or host, port +func SetAddr(s ...string) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + if len(s) == 1 { + split := strings.SplitN(s[0], ":", 2) + if len(split) == 2 { + if i, err := strconv.Atoi(split[1]); err == nil { + if i < 65536 { + c.SamHost = split[0] + c.SamPort = split[1] + return nil + } + return fmt.Errorf("Invalid port") + } + return fmt.Errorf("Invalid port; non-number") + } + return fmt.Errorf("Invalid address; use host:port %s", split) + } else if len(s) == 2 { + if i, err := strconv.Atoi(s[1]); err == nil { + if i < 65536 { + c.SamHost = s[0] + c.SamPort = s[1] + return nil + } + return fmt.Errorf("Invalid port") + } + return fmt.Errorf("Invalid port; non-number") + } else { + return fmt.Errorf("Invalid address") + } + } +} + +//SetAddrMixed sets a clients's address in the form host, port(int) +func SetAddrMixed(s string, i int) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + if i < 65536 && i > 0 { + c.SamHost = s + c.SamPort = strconv.Itoa(i) + return nil + } + return fmt.Errorf("Invalid port") + } +} + +//SetHost sets the host of the client's SAM bridge +func SetHost(s string) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + c.SamHost = s + return nil + } +} + +//SetPort sets the port of the client's SAM bridge using a string +func SetPort(s string) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + port, err := strconv.Atoi(s) + if err != nil { + return fmt.Errorf("Invalid port; non-number") + } + if port < 65536 && port > -1 { + c.SamPort = s + return nil + } + return fmt.Errorf("Invalid port") + } +} + +//SetPortInt sets the port of the client's SAM bridge using a string +func SetPortInt(i int) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + if i < 65536 && i > -1 { + c.SamPort = strconv.Itoa(i) + return nil + } + return fmt.Errorf("Invalid port") + } +} + +//SetDebug enables debugging messages +func SetDebug(b bool) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + c.debug = b + return nil + } +} + +//SetInLength sets the number of hops inbound +func SetInLength(u uint) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + if u < 7 { + c.inLength = u + return nil + } + return fmt.Errorf("Invalid inbound tunnel length") + } +} + +//SetOutLength sets the number of hops outbound +func SetOutLength(u uint) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + if u < 7 { + c.outLength = u + return nil + } + return fmt.Errorf("Invalid outbound tunnel length") + } +} + +//SetInVariance sets the variance of a number of hops inbound +func SetInVariance(i int) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + if i < 7 && i > -7 { + c.inVariance = i + return nil + } + return fmt.Errorf("Invalid inbound tunnel length") + } +} + +//SetOutVariance sets the variance of a number of hops outbound +func SetOutVariance(i int) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + if i < 7 && i > -7 { + c.outVariance = i + return nil + } + return fmt.Errorf("Invalid outbound tunnel variance") + } +} + +//SetInQuantity sets the inbound tunnel quantity +func SetInQuantity(u uint) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + if u <= 16 { + c.inQuantity = u + return nil + } + return fmt.Errorf("Invalid inbound tunnel quantity") + } +} + +//SetOutQuantity sets the outbound tunnel quantity +func SetOutQuantity(u uint) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + if u <= 16 { + c.outQuantity = u + return nil + } + return fmt.Errorf("Invalid outbound tunnel quantity") + } +} + +//SetInBackups sets the inbound tunnel backups +func SetInBackups(u uint) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + if u < 6 { + c.inBackups = u + return nil + } + return fmt.Errorf("Invalid inbound tunnel backup quantity") + } +} + +//SetOutBackups sets the inbound tunnel backups +func SetOutBackups(u uint) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + if u < 6 { + c.outBackups = u + return nil + } + return fmt.Errorf("Invalid outbound tunnel backup quantity") + } +} + +//SetUnpublished tells the router to not publish the client leaseset +func SetUnpublished(b bool) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + c.dontPublishLease = b + return nil + } +} + +//SetEncrypt tells the router to use an encrypted leaseset +func SetEncrypt(b bool) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + c.encryptLease = b + return nil + } +} + +//SetReduceIdle sets the created tunnels to be reduced during extended idle time to avoid excessive resource usage +func SetReduceIdle(b bool) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + c.reduceIdle = b + return nil + } +} + +//SetReduceIdleTime sets time to wait before the tunnel quantity is reduced +func SetReduceIdleTime(u uint) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + if u > 300000 { + c.reduceIdleTime = u + return nil + } + return fmt.Errorf("Invalid reduce idle time %v", u) + } +} + +//SetReduceIdleQuantity sets number of tunnels to keep alive during an extended idle period +func SetReduceIdleQuantity(u uint) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + if u < 5 { + c.reduceIdleQuantity = u + return nil + } + return fmt.Errorf("Invalid reduced tunnel quantity %v", u) + } +} + +//SetCompression sets the tunnels to close after a specific amount of time +func SetCompression(b bool) func(*SAMHTTPProxy) error { + return func(c *SAMHTTPProxy) error { + c.compression = b + return nil + } +} + +//return the inbound length as a string. +func (c *SAMHTTPProxy) inlength() string { + return fmt.Sprintf("inbound.length=%d", c.inLength) +} + +//return the outbound length as a string. +func (c *SAMHTTPProxy) outlength() string { + return fmt.Sprintf("outbound.length=%d", c.outLength) +} + +//return the inbound length variance as a string. +func (c *SAMHTTPProxy) invariance() string { + return fmt.Sprintf("inbound.lengthVariance=%d", c.inVariance) +} + +//return the outbound length variance as a string. +func (c *SAMHTTPProxy) outvariance() string { + return fmt.Sprintf("outbound.lengthVariance=%d", c.outVariance) +} + +//return the inbound tunnel quantity as a string. +func (c *SAMHTTPProxy) inquantity() string { + return fmt.Sprintf("inbound.quantity=%d", c.inQuantity) +} + +//return the outbound tunnel quantity as a string. +func (c *SAMHTTPProxy) outquantity() string { + return fmt.Sprintf("outbound.quantity=%d", c.outQuantity) +} + +//return the inbound tunnel quantity as a string. +func (c *SAMHTTPProxy) inbackups() string { + return fmt.Sprintf("inbound.backupQuantity=%d", c.inQuantity) +} + +//return the outbound tunnel quantity as a string. +func (c *SAMHTTPProxy) outbackups() string { + return fmt.Sprintf("outbound.backupQuantity=%d", c.outQuantity) +} + +func (c *SAMHTTPProxy) encryptlease() string { + if c.encryptLease { + return "i2cp.encryptLeaseSet=true" + } + return "i2cp.encryptLeaseSet=false" +} + +func (c *SAMHTTPProxy) dontpublishlease() string { + if c.dontPublishLease { + return "i2cp.dontPublishLeaseSet=true" + } + return "i2cp.dontPublishLeaseSet=false" +} + +func (c *SAMHTTPProxy) reduceonidle() string { + if c.reduceIdle { + return "i2cp.reduceOnIdle=true" + } + return "i2cp.reduceOnIdle=false" +} + +func (c *SAMHTTPProxy) reduceidletime() string { + return fmt.Sprintf("i2cp.reduceIdleTime=%d", c.reduceIdleTime) +} + +func (c *SAMHTTPProxy) reduceidlecount() string { + return fmt.Sprintf("i2cp.reduceIdleQuantity=%d", c.reduceIdleQuantity) +} + +func (c *SAMHTTPProxy) compresion() string { + if c.compression { + return "i2cp.gzip=true" + } + return "i2cp.gzip=false" +} diff --git a/httptunnel.go b/httptunnel.go index 7616dda..bb798d0 100644 --- a/httptunnel.go +++ b/httptunnel.go @@ -11,8 +11,36 @@ import ( import ( "github.com/eyedeekay/goSam" + "github.com/eyedeekay/sam3" ) +type SAMHTTPProxy struct { + gosam *goSam.Client + Client *http.Client + samcon *sam3.SAM + keys sam3.I2PKeys + stream *sam3.StreamSession + SamHost string + SamPort string + TunName string + inLength uint + outLength uint + inVariance int + outVariance int + inQuantity uint + outQuantity uint + inBackups uint + outBackups uint + dontPublishLease bool + encryptLease bool + reduceIdle bool + reduceIdleTime uint + reduceIdleQuantity uint + compression bool + + debug bool +} + func copyHeader(dst, src http.Header) { for k, vv := range src { for _, v := range vv { @@ -38,15 +66,10 @@ func delHopHeaders(header http.Header) { } } -type Proxy struct { - Sam *goSam.Client - Client *http.Client -} - -func (p *Proxy) freshClient() *http.Client { +func (p *SAMHTTPProxy) freshClient() *http.Client { return &http.Client{ Transport: &http.Transport{ - Dial: p.Sam.Dial, + Dial: p.gosam.Dial, MaxIdleConns: 0, MaxIdleConnsPerHost: 3, DisableKeepAlives: false, @@ -62,7 +85,7 @@ func (p *Proxy) freshClient() *http.Client { } -func (p *Proxy) ServeHTTP(wr http.ResponseWriter, req *http.Request) { +func (p *SAMHTTPProxy) ServeHTTP(wr http.ResponseWriter, req *http.Request) { log.Println(req.RemoteAddr, " ", req.Method, " ", req.URL) if req.URL.Scheme != "http" && req.URL.Scheme != "https" && !strings.HasSuffix(req.URL.Host, ".i2p") { @@ -72,14 +95,44 @@ func (p *Proxy) ServeHTTP(wr http.ResponseWriter, req *http.Request) { return } - req.RequestURI = "" + if req.Method == http.MethodConnect { + log.Println("Connecting tunnel") + p.connect(wr, req) + } else { + req.RequestURI = "" + delHopHeaders(req.Header) + p.get(wr, req) + } - delHopHeaders(req.Header) - - p.get(wr, req) } -func (p *Proxy) get(wr http.ResponseWriter, req *http.Request) { +func (p *SAMHTTPProxy) connect(wr http.ResponseWriter, req *http.Request) { + dest_conn, err := p.stream.Dial("tcp", req.Host) + if err != nil { + http.Error(wr, err.Error(), http.StatusServiceUnavailable) + return + } + wr.WriteHeader(http.StatusOK) + hijacker, ok := wr.(http.Hijacker) + if !ok { + http.Error(wr, "Hijacking not supported", http.StatusInternalServerError) + return + } + client_conn, _, err := hijacker.Hijack() + if err != nil { + http.Error(wr, err.Error(), http.StatusServiceUnavailable) + } + go transfer(dest_conn, client_conn) + go transfer(client_conn, dest_conn) +} + +func transfer(destination io.WriteCloser, source io.ReadCloser) { + defer destination.Close() + defer source.Close() + io.Copy(destination, source) +} + +func (p *SAMHTTPProxy) get(wr http.ResponseWriter, req *http.Request) { Client := p.freshClient() resp, err := Client.Do(req) if err != nil { @@ -92,38 +145,92 @@ func (p *Proxy) get(wr http.ResponseWriter, req *http.Request) { io.Copy(wr, resp.Body) } -func NewHttpProxy() (*Proxy, error) { - sam, err := goSam.NewClientFromOptions( - goSam.SetHost("127.0.0.1"), - goSam.SetPort("7656"), - goSam.SetUnpublished(true), - goSam.SetInLength(uint(2)), - goSam.SetOutLength(uint(2)), - goSam.SetInQuantity(uint(4)), - goSam.SetOutQuantity(uint(4)), - goSam.SetInBackups(uint(2)), - goSam.SetOutBackups(uint(2)), - goSam.SetReduceIdle(true), - goSam.SetReduceIdleTime(uint(2000000)), +func (p *SAMHTTPProxy) sam3Args() []string { + return []string{ + p.inlength(), + p.outlength(), + p.invariance(), + p.outvariance(), + p.inquantity(), + p.outquantity(), + p.inbackups(), + p.outbackups(), + p.dontpublishlease(), + p.encryptlease(), + p.reduceonidle(), + p.reduceidletime(), + p.reduceidlecount(), + "i2cp.gzip=true", + } +} + +func NewHttpProxy(opts ...func(*SAMHTTPProxy) error) (*SAMHTTPProxy, error) { + var handler SAMHTTPProxy + handler.SamHost = "127.0.0.1" + handler.SamPort = "7656" + handler.TunName = "sam-http-proxy" + handler.inLength = 2 + handler.outLength = 2 + handler.inVariance = 0 + handler.outVariance = 0 + handler.inQuantity = 1 + handler.outQuantity = 1 + handler.inBackups = 1 + handler.outBackups = 1 + handler.dontPublishLease = true + handler.encryptLease = false + handler.reduceIdle = false + handler.reduceIdleTime = 2000000 + handler.reduceIdleQuantity = 1 + for _, o := range opts { + if err := o(&handler); err != nil { + return nil, err + } + } + var err error + handler.gosam, err = goSam.NewClientFromOptions( + goSam.SetHost(handler.SamHost), + goSam.SetPort(handler.SamPort), + goSam.SetUnpublished(handler.dontPublishLease), + goSam.SetInLength(handler.inLength), + goSam.SetOutLength(handler.outLength), + goSam.SetInQuantity(handler.inQuantity), + goSam.SetOutQuantity(handler.outQuantity), + goSam.SetInBackups(handler.inBackups), + goSam.SetOutBackups(handler.outBackups), + goSam.SetReduceIdle(handler.reduceIdle), + goSam.SetReduceIdleTime(handler.reduceIdleTime), + goSam.SetReduceIdleQuantity(handler.reduceIdleQuantity), ) - return nil, err - handler := Proxy{ - Sam: sam, - Client: &http.Client{ - Transport: &http.Transport{ - Dial: sam.Dial, - MaxIdleConns: 0, - MaxIdleConnsPerHost: 3, - DisableKeepAlives: false, - ResponseHeaderTimeout: time.Second * 600, - ExpectContinueTimeout: time.Second * 600, - IdleConnTimeout: time.Second * 600, - TLSNextProto: make(map[string]func(authority string, c *tls.Conn) http.RoundTripper), - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - }, - CheckRedirect: nil, - Timeout: time.Second * 600, + if err != nil { + return nil, err + } + handler.samcon, err = sam3.NewSAM(handler.SamHost + ":" + handler.SamPort) + if err != nil { + return nil, err + } + handler.keys, err = handler.samcon.NewKeys() + if err != nil { + return nil, err + } + handler.stream, err = handler.samcon.NewStreamSession("sam-http-connector", handler.keys, handler.sam3Args()) + if err != nil { + return nil, err + } + handler.Client = &http.Client{ + Transport: &http.Transport{ + Dial: handler.gosam.Dial, + MaxIdleConns: 0, + MaxIdleConnsPerHost: 3, + DisableKeepAlives: false, + ResponseHeaderTimeout: time.Second * 600, + ExpectContinueTimeout: time.Second * 600, + IdleConnTimeout: time.Second * 600, + //TLSNextProto: make(map[string]func(authority string, c *tls.Conn) http.RoundTripper), + //TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, }, + CheckRedirect: nil, + Timeout: time.Second * 600, } return &handler, nil } diff --git a/windows/main.go b/windows/main.go index 40dea0b..b6e2906 100644 --- a/windows/main.go +++ b/windows/main.go @@ -4,19 +4,79 @@ import ( "flag" "log" "net/http" + "time" +) + +import ( + . "github.com/eyedeekay/httptunnel" +) + +var ( + //tunnelName = flag.String("service-name", "sam-http-proxy", "Name of the service(can be anything)") + samHostString = flag.String("bridge-host", "127.0.0.1", "host: of the SAM bridge") + samPortString = flag.String("bridge-port", "7656", ":port of the SAM bridge") + proxHostString = flag.String("proxy-host", "127.0.0.1", "host: of the HTTP proxy") + proxPortString = flag.String("proxy-port", "7950", ":port of the HTTP proxy") + debugConnection = flag.Bool("conn-debug", false, "Print connection debug info") + inboundTunnelLength = flag.Int("in-tun-length", 3, "Tunnel Length(default 3)") + outboundTunnelLength = flag.Int("out-tun-length", 3, "Tunnel Length(default 3)") + inboundTunnels = flag.Int("in-tunnels", 4, "Inbound Tunnel Count(default 8)") + outboundTunnels = flag.Int("out-tunnels", 2, "Outbound Tunnel Count(default 8)") + inboundBackups = flag.Int("in-backups", 3, "Inbound Backup Count(default 3)") + outboundBackups = flag.Int("out-backups", 3, "Inbound Backup Count(default 3)") + inboundVariance = flag.Int("in-variance", 3, "Inbound Backup Count(default 3)") + outboundVariance = flag.Int("out-variance", 3, "Inbound Backup Count(default 3)") + dontPublishLease = flag.Bool("no-publish", true, "Don't publish the leaseset(Client mode)") + //encryptLease = flag.Bool("encrypt-lease", true, "Encrypt the leaseset(") + reduceIdle = flag.Bool("reduce-idle", false, "Reduce tunnels on extended idle time") + reduceIdleTime = flag.Int("reduce-idle-time", 2000000, "Reduce tunnels after time(Ms)") + reduceIdleQuantity = flag.Int("reduce-idle-tunnels", 1, "Reduce tunnels to this level") ) func main() { - var addr = flag.String("addr", "127.0.0.1:7950", "The addr of the application.") flag.Parse() + addr := *proxHostString + ":" + *proxPortString - handler, err := NewHttpProxy() + srv := &http.Server{ + ReadTimeout: 600 * time.Second, + WriteTimeout: 600 * time.Second, + Addr: addr, + } + var err error + srv.Handler, err = NewHttpProxy( + SetHost(*samHostString), + SetPort(*samPortString), + SetDebug(*debugConnection), + SetInLength(uint(*inboundTunnelLength)), + SetOutLength(uint(*outboundTunnelLength)), + SetInQuantity(uint(*inboundTunnels)), + SetOutQuantity(uint(*outboundTunnels)), + SetInBackups(uint(*inboundBackups)), + SetOutBackups(uint(*outboundBackups)), + SetInVariance(*inboundVariance), + SetOutVariance(*outboundVariance), + SetUnpublished(*dontPublishLease), + SetReduceIdle(*reduceIdle), + SetReduceIdleTime(uint(*reduceIdleTime)), + SetReduceIdleQuantity(uint(*reduceIdleQuantity)), + ) if err != nil { log.Fatal(err) } - log.Println("Starting proxy server on", *addr) - if err := http.ListenAndServe(*addr, handler); err != nil { + go counter() + + log.Println("Starting proxy server on", addr) + if err := srv.ListenAndServe(); err != nil { log.Fatal("ListenAndServe:", err) } } + +func counter() { + var x int + for { + log.Println("Identity is", x, "minute(s) old") + time.Sleep(1 * time.Minute) + x++ + } +}