Пример #1
0
func main() {
	bl := Create()
	proxy := goproxy.NewProxyHttpServer()
	proxy.Verbose = false
	proxy.OnRequest(goproxy.DstHostIs("nogame")).DoFunc(bl.conf)
	proxy.OnRequest().DoFunc(bl.checkHost)
	log.Fatal(http.ListenAndServe(":8080", proxy))
}
Пример #2
0
func main() {
	proxy := goproxy.NewProxyHttpServer()
	proxy.OnRequest(goproxy.DstHostIs("www.reddit.com")).DoFunc(
		func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
			if h, _, _ := time.Now().Clock(); h >= 8 && h <= 17 {
				return r, goproxy.NewResponse(r,
					goproxy.ContentTypeText, http.StatusForbidden,
					"Don't waste your time!")
			}
			return r, nil
		})
	log.Fatalln(http.ListenAndServe(":8080", proxy))
}
Пример #3
0
func main() {
	flag.Parse()
	init_datastore(*datastore)

	proxy := goproxy.NewProxyHttpServer()
	proxy.Verbose = *verbose

	// Requests for eccaHandlerHost allow the user to select and create certificates
	// This handler sends a response to the client, never upstream.
	proxy.OnRequest(goproxy.DstHostIs(eccaHandlerHost)).DoFunc(eccaHandler)

	// All other requests (where the user want to go to) are handled here.
	// When this needs an account, it redirects the client to the eccaHandler above.
	proxy.OnRequest().DoFunc(eccaProxy)

	// Decode any messages when we have the "Eccentric-Authentication" header set to "decrypt"
	proxy.OnResponse().DoFunc(DecodeMessages)

	// Verify any messages where we have the Eccentric-Authentication header set to "verification"
	proxy.OnResponse().DoFunc(VerifyMessages)

	// Change the redirect location (from https) to http so the client gets back to us.
	proxy.OnResponse().DoFunc(ChangeToHttp)

	restartAllTorListeners()

	log.Printf("Starting proxy access at [::1]:%d and at 127.0.0.1:%d\n", *port, *port)
	log.Printf("Configure your browser to use one of those as http-proxy.\n")
	log.Printf("Then browse to http://dating.wtmnd.nl:10443/\n")
	log.Printf("Use http (not https) to benefit from this proxy.\n")
	log.Printf("For assistence, please see: http://eccentric-authentication.org/contact.html\n")

	server6 := &http.Server{
		Addr:    fmt.Sprintf("[::1]:%d", *port),
		Handler: proxy,
	}
	// TODO: disable KeepAlives when your golang version supports it
	//server6.SetKeepAlivesEnabled(false)

	server4 := &http.Server{
		Addr:    fmt.Sprintf("127.0.0.1:%d", *port),
		Handler: proxy,
	}
	// TODO: disable KeepAlives when your golang version supports it
	//server4.SetKeepAlivesEnabled(false)

	// run or die. Try ipv6 first
	go server6.ListenAndServe()
	log.Fatal(server4.ListenAndServe())
}
Пример #4
0
func main() {
	proxy := goproxy.NewProxyHttpServer()
	proxy.Verbose = *verbose
	if proxy.Verbose {
		log.Printf("Server starting up! - configured to listen on http interface %s and https interface %s with hostname %s", *http_addr, *https_addr, *proxy_hostname)
	}

	proxy.NonproxyHandler = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		if req.Host == "" {
			fmt.Fprintln(w, "Cannot handle requests without Host header, e.g., HTTP 1.0")
			return
		}
		req.URL.Scheme = "http"
		req.URL.Host = req.Host
		proxy.ServeHTTP(w, req)
	})
	cert, err := tls.LoadX509KeyPair("ca.crt", "ca.key")
	if err != nil {
		log.Fatalf("Unable to load certificate - %v", err)
	}

	proxy.OnRequest(goproxy.DstHostIs(*proxy_hostname)).DoFunc(whitelistService)
	proxy.OnRequest().DoFunc(whiteListHandler)
	proxy.OnRequest().HandleConnectFunc(func(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) {
		ip, _, err := net.SplitHostPort(ctx.Req.RemoteAddr)
		if err != nil {
			panic(fmt.Sprintf("userip: %q is not IP:port", ctx.Req.RemoteAddr))
		}
		userIP := net.ParseIP(ip)
		if userIP == nil {
			panic(fmt.Sprintf("userip: %q is not IP", ip))
		}
		log.Printf("Handled connect from ip - %s - for host %s", ip, host)
		if err != nil {
			log.Printf("Error creating URL for host %s", host)
		} else if host != *proxy_hostname && wlm.Check(userIP, Site{
			URL:     ctx.Req.URL,
			Referer: "pressl",
		}) {
			// don't tear down the SSL session
			return &goproxy.ConnectAction{
				Action: goproxy.ConnectAccept,
			}, host + ":443"
		}
		return &goproxy.ConnectAction{
			Action:    goproxy.ConnectMitm,
			TLSConfig: goproxy.TLSConfigFromCA(&cert),
		}, host + ":443"
	})

	go func() {
		log.Fatalln(http.ListenAndServe(*http_addr, proxy))
	}()

	// listen to the TLS ClientHello but make it a CONNECT request instead
	ln, err := net.Listen("tcp", *https_addr)
	if err != nil {
		log.Fatalf("Error listening for https connections - %v", err)
	}
	for {
		c, err := ln.Accept()
		if err != nil {
			log.Printf("Error accepting new connection - %v", err)
			continue
		}
		go func(c net.Conn) {
			tlsConn, err := vhost.TLS(c)
			if err != nil {
				log.Printf("Error accepting new connection - %v", err)
			}
			host := tlsConn.Host()
			if host == "" {
				log.Printf("Cannot support non-SNI enabled clients, attempting to make an educated guess")
				// TODO: add other options than dnsmasq through journald
				cmd := exec.Command(
					"/usr/bin/sudo",
					"/usr/bin/journalctl",
					"-n 20",
				)
				output, err := cmd.CombinedOutput()
				if err != nil {
					log.Printf("Could not find a recent DNS lookup in the dnsmasq logs - %v", err)
				} else {
					lines := bufio.NewScanner(bytes.NewReader(output))
					requestor, _, _ := net.SplitHostPort(c.RemoteAddr().String())
					for lines.Scan() {
						if strings.Contains(lines.Text(), requestor) {
							split := strings.Split(lines.Text(), " ")
							if len(split) >= 7 {
								host = split[6]
								break
							}
						}
					}
				}
				if host == "" {
					// At this point we're going to error, give the client a hint as to why
					host = "yourclientdoesnotsuppportsni"
				}
				log.Printf("Guessing with %s", host)
			}
			connectReq := &http.Request{
				RemoteAddr: c.RemoteAddr().String(),
				Method:     "CONNECT",
				URL: &url.URL{
					Opaque: host,
					Host:   host,
				},
				Host:   host,
				Header: make(http.Header),
			}
			log.Printf("Making faux CONNECT request with URL - %s", connectReq.URL)
			log.Printf("Request.URL.Host - %v", connectReq.URL.Host)
			resp := dumbResponseWriter{tlsConn}
			proxy.ServeHTTP(resp, connectReq)
		}(c)
	}
}
Пример #5
0
func myproxy() {

    pname := "HttpProxy4U"
    pver := "1.0.0"

    // get current working directory
    cwd, err := os.Getwd()
    checkError(err)

    // parse input parameters
	var port, wlistFile, blistFile, rulesFile, aname, apwd, tdir, rdir string
	var verbose int
    var interval int64
	flag.StringVar(&port, "port", ":9998", "Proxy port number")
	flag.StringVar(&tdir, "tmpl-dir",
            filepath.Join(cwd, "static/tmpl"), "Template directory")
	flag.StringVar(&rdir, "rule-dir",
            filepath.Join(cwd, "static/rules"), "Rules directory")
	flag.StringVar(&wlistFile, "whitelist",
            filepath.Join(rdir, "whitelist.txt"), "White list file")
	flag.StringVar(&blistFile, "blacklist",
            filepath.Join(rdir, "blacklist.txt"), "Black list file")
	flag.StringVar(&rulesFile, "rules",
            filepath.Join(rdir, "rules.txt"), "Rules list file")
	flag.IntVar(&verbose, "verbose", 0, "logging level")
	flag.Int64Var(&interval, "interval", 300, "reload interval")
	flag.StringVar(&aname, "login", "admin", "Admin login name")
	flag.StringVar(&apwd, "password", "test", "Admin password")
	flag.Parse()

	// init proxy server
	proxy := goproxy.NewProxyHttpServer()
    proxy.Verbose = false // true
    if verbose > 1 {
        proxy.Verbose = true
    }
	msg := fmt.Sprintf("port=%s, verbose=%d, wlist=%s, blist=%s, rule=%s",
            port, verbose, wlistFile, blistFile, rulesFile)
	log.Println(msg)

    // read out client settings
	whitelist := readTxtFile(wlistFile)
	log.Println("White list:", whitelist)
	blacklist := readTxtFile(blistFile)
	log.Println("Black list:", blacklist)
	ruleslist := parseRules(readCSVFile(rulesFile))
	log.Println("Rules list:", ruleslist)
    lastRead := time.Now().UTC().Unix()

    // local variables
    var rules []string
    for _, r := range ruleslist {
        rules = append(rules, r.ToCSV())
    }
    tcss := "main.tmpl.css"
    tmplData := map[string]interface{}{}
    css := parseTmpl(tdir, tcss, tmplData)
    tfooter := "footer.tmpl.html"
    tmplData["package"] = pname
    tmplData["version"] = pver
    tmplData["css"] = css
    footer := parseTmpl(tdir, tfooter, tmplData)
    tmplData["whitelist"] = strings.Join(whitelist, "\n")
    tmplData["blacklist"] = strings.Join(blacklist, "\n")
    tmplData["ruleslist"] = strings.Join(rules, "\n")
    tmplData["footer"] = footer

	// admin handler
//    proxy.OnRequest(goproxy.IsLocalHost).DoFunc(
    proxy.OnRequest(goproxy.DstHostIs("")).DoFunc(
		func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
            path := html.EscapeString(r.URL.Path)
            log.Println("admin interface", path)
            if path == "/admin" {
                tauth := "auth.tmpl.html"
                u := r.FormValue("login")
                p := r.FormValue("password")
                if u == aname && p == apwd {
                    log.Println("access admin interface")
                } else {
                    return r, goproxy.NewResponse(r, goproxy.ContentTypeHtml,
                        http.StatusOK, parseTmpl(tdir, tauth, tmplData))
                }
                tpage := "admin.tmpl.html"
                return r, goproxy.NewResponse(r, goproxy.ContentTypeHtml,
                    http.StatusOK, parseTmpl(tdir, tpage, tmplData))
            } else if path == "/save" {
                wlist := strip(r.FormValue("whitelist"))
                blist := strip(r.FormValue("blacklist"))
                rlist := strip(r.FormValue("ruleslist"))
                saveList(wlistFile, wlist)
                saveList(blistFile, blist)
                saveList(rulesFile, rlist)
                tmplData["whitelist"] = wlist
                tmplData["blacklist"] = blist
                tmplData["ruleslist"] = rlist
                tpage := "save.tmpl.html"
                tmplData["body"] = fmt.Sprintf("New rules has been saved on %s",
                        time.Now())
                return r, goproxy.NewResponse(r, goproxy.ContentTypeHtml,
                    http.StatusOK, parseTmpl(tdir, tpage, tmplData))
            } else {
                tpage := "index.tmpl.html"
                return r, goproxy.NewResponse(r, goproxy.ContentTypeHtml,
                    http.StatusOK, parseTmpl(tdir, tpage, tmplData))
            }
		})

	// restrict certain sites on time based rules
	for _, rule := range ruleslist {
		proxy.OnRequest(goproxy.DstHostIs(rule.Url)).DoFunc(
			func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
                // reload maps if necessary
                unix := time.Now().UTC().Unix()
                if  unix-lastRead > interval {
                    ruleslist := parseRules(readCSVFile(rulesFile))
                    if verbose > 0 {
                        log.Println("Rules list:", ruleslist)
                    }
                    lastRead = unix
                }
				h, _, _ := time.Now().Clock()
				if h < rule.MinHour && h > rule.MaxHour {
					return r, goproxy.NewResponse(r,
						goproxy.ContentTypeText, http.StatusForbidden,
						"Your exceed your time window on this site")
				}
				return r, nil
			})
	}

	// filter white/black lists
	proxy.OnRequest().DoFunc(
		func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
            // reload maps if necessary
            unix := time.Now().UTC().Unix()
            if  unix-lastRead > interval {
                whitelist := readTxtFile(wlistFile)
                blacklist := readTxtFile(blistFile)
                if verbose > 0 {
                    log.Println("Reload white list:", whitelist)
                    log.Println("Reload black list:", blacklist)
                }
                lastRead = unix
            }
			pat1 := strings.Join(whitelist, "|")
			expect1 := false // match=false means site not in whitelist
			match1, err := regexp.MatchString(pat1, r.URL.Host)
			if err != nil {
				log.Println("ERROR: fail in match", pat1, r.URL.Host)
			}
			pat2 := strings.Join(blacklist, "|")
			expect2 := true // match=true means site is in blacklist
			match2, err := regexp.MatchString(pat2, r.URL.Host)
			if err != nil {
				log.Println("ERROR: fail in match", pat2, r.URL.Host)
			}
			if match2 == expect2 || match1 == expect1 {
				path := html.EscapeString(r.URL.Path)
				if verbose > 0 {
					log.Println(r.URL.Host, path)
				}
				return r, goproxy.NewResponse(r,
					goproxy.ContentTypeText, http.StatusForbidden,
					"This site is not accessible to you")
			}
			return r, nil
		})

	// start and log http proxy server
	log.Fatal(http.ListenAndServe(port, proxy))
}
Пример #6
0
func TestHttpsMitmURLRewrite(t *testing.T) {
	scheme := "https"

	testCases := []struct {
		Host      string
		RawPath   string
		AddOpaque bool
	}{
		{
			Host:      "example.com",
			RawPath:   "/blah/v1/data/realtime",
			AddOpaque: true,
		},
		{
			Host:    "example.com:443",
			RawPath: "/blah/v1/data/realtime?encodedURL=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile",
		},
		{
			Host:    "example.com:443",
			RawPath: "/blah/v1/data/realtime?unencodedURL=https://www.googleapis.com/auth/userinfo.profile",
		},
	}

	for _, tc := range testCases {
		proxy := goproxy.NewProxyHttpServer()
		proxy.OnRequest().HandleConnect(goproxy.AlwaysMitm)

		proxy.OnRequest(goproxy.DstHostIs(tc.Host)).DoFunc(
			func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
				return nil, goproxy.TextResponse(req, "Dummy response")
			})

		client, s := oneShotProxy(proxy, t)
		defer s.Close()

		fullURL := scheme + "://" + tc.Host + tc.RawPath
		req, err := http.NewRequest("GET", fullURL, nil)
		if err != nil {
			t.Fatal(err)
		}

		if tc.AddOpaque {
			req.URL.Scheme = scheme
			req.URL.Opaque = "//" + tc.Host + tc.RawPath
		}

		resp, err := client.Do(req)

		if err != nil {
			t.Fatal(err)
		}

		b, err := ioutil.ReadAll(resp.Body)
		defer resp.Body.Close()
		if err != nil {
			t.Fatal(err)
		}

		body := string(b)
		if body != "Dummy response" {
			t.Errorf("Expected proxy to return dummy body content but got %s", body)
		}

		if resp.StatusCode != http.StatusAccepted {
			t.Errorf("Expected status: %d, got: %d", http.StatusAccepted, resp.StatusCode)
		}
	}
}