func main() { flag.Parse() p := martian.NewProxy() var x509c *x509.Certificate var priv interface{} if *generateCA { var err error x509c, priv, err = mitm.NewAuthority("martian.proxy", "Martian Authority", 30*24*time.Hour) if err != nil { log.Fatal(err) } } else if *cert != "" && *key != "" { tlsc, err := tls.LoadX509KeyPair(*cert, *key) if err != nil { log.Fatal(err) } priv = tlsc.PrivateKey x509c, err = x509.ParseCertificate(tlsc.Certificate[0]) if err != nil { log.Fatal(err) } } if x509c != nil && priv != nil { mc, err := mitm.NewConfig(x509c, priv) if err != nil { log.Fatal(err) } mc.SetValidity(*validity) mc.SetOrganization(*organization) p.SetMITM(mc) // Expose certificate authority. ah := martianhttp.NewAuthorityHandler(x509c) configure("/authority.cer", ah) } fg := fifo.NewGroup() hbhm := header.NewHopByHopModifier() fg.AddRequestModifier(hbhm) fg.AddRequestModifier(header.NewForwardedModifier()) fg.AddRequestModifier(header.NewBadFramingModifier()) vm := header.NewViaModifier("martian") fg.AddRequestModifier(vm) m := martianhttp.NewModifier() fg.AddRequestModifier(m) fg.AddResponseModifier(m) fg.AddResponseModifier(hbhm) fg.AddResponseModifier(vm) p.SetRequestModifier(fg) p.SetResponseModifier(fg) // Proxy specific handlers. // These handlers take precendence over proxy traffic and will not be // intercepted. // Configure modifiers. configure("/configure", m) // Verify assertions. vh := verify.NewHandler() vh.SetRequestVerifier(m) vh.SetResponseVerifier(m) configure("/verify", vh) // Reset verifications. rh := verify.NewResetHandler() rh.SetRequestVerifier(m) rh.SetResponseVerifier(m) configure("/verify/reset", rh) l, err := net.Listen("tcp", *addr) if err != nil { log.Fatal(err) } log.Println("martian: proxy started on:", l.Addr()) go p.Serve(l) sigc := make(chan os.Signal, 1) signal.Notify(sigc, os.Interrupt, os.Kill) <-sigc log.Println("martian: shutting down") }
func main() { flag.Parse() var mitm *martian.MITM if *cert != "" && *key != "" { tlsc, err := tls.LoadX509KeyPair(*cert, *key) if err != nil { log.Fatal(err) } x509c, err := x509.ParseCertificate(tlsc.Certificate[0]) if err != nil { log.Fatal(err) } var pub crypto.PublicKey switch priv := tlsc.PrivateKey.(type) { case *rsa.PrivateKey: pub = &priv.PublicKey case *ecdsa.PrivateKey: pub = &priv.PublicKey default: log.Fatal("Public key is not of supported type: rsa, ecdsa.") } mitm = &martian.MITM{ Authority: x509c, PublicKey: pub, PrivateKey: tlsc.PrivateKey, Validity: *validity, Organization: *organization, } } p := martian.NewProxy(mitm) m := martianhttp.NewModifier() fg := fifo.NewGroup() fg.AddRequestModifier(m) fg.AddResponseModifier(m) p.SetRequestModifier(fg) p.SetResponseModifier(fg) // Proxy specific handlers. // These handlers take precendence over proxy traffic and will not be // intercepted. // Update modifiers. configure("martian/modifiers", m) // Verify assertions. vh := verify.NewHandler() vh.SetRequestVerifier(m) vh.SetResponseVerifier(m) configure("martian/verify", vh) // Reset verifications. rh := verify.NewResetHandler() rh.SetRequestVerifier(m) rh.SetResponseVerifier(m) configure("martian/verify/reset", rh) // Forward all other requests to the proxy. http.Handle("/", p) log.Printf("Martian started at %s", *addr) log.Fatal(http.ListenAndServe(*addr, nil)) }
func main() { flag.Parse() mlog.SetLevel(*level) p := martian.NewProxy() // Respond with 404 to any unknown proxy path. http.HandleFunc(*api+"/", http.NotFound) var x509c *x509.Certificate var priv interface{} if *generateCA { var err error x509c, priv, err = mitm.NewAuthority("martian.proxy", "Martian Authority", 30*24*time.Hour) if err != nil { log.Fatal(err) } } else if *cert != "" && *key != "" { tlsc, err := tls.LoadX509KeyPair(*cert, *key) if err != nil { log.Fatal(err) } priv = tlsc.PrivateKey x509c, err = x509.ParseCertificate(tlsc.Certificate[0]) if err != nil { log.Fatal(err) } } if x509c != nil && priv != nil { mc, err := mitm.NewConfig(x509c, priv) if err != nil { log.Fatal(err) } mc.SetValidity(*validity) mc.SetOrganization(*organization) mc.SkipTLSVerify(*skipTLSVerify) p.SetMITM(mc) // Expose certificate authority. ah := martianhttp.NewAuthorityHandler(x509c) configure("/authority.cer", ah) // Start TLS listener for transparent MITM. tl, err := net.Listen("tcp", *tlsAddr) if err != nil { log.Fatal(err) } go p.Serve(tls.NewListener(tl, mc.TLS())) } stack, fg := httpspec.NewStack("martian") p.SetRequestModifier(stack) p.SetResponseModifier(stack) m := martianhttp.NewModifier() fg.AddRequestModifier(m) fg.AddResponseModifier(m) if *harLogging { hl := har.NewLogger("martian", "2.0.0") stack.AddRequestModifier(hl) stack.AddResponseModifier(hl) configure("/logs", har.NewExportHandler(hl)) configure("/logs/reset", har.NewResetHandler(hl)) } // Proxy specific handlers. // These handlers take precendence over proxy traffic and will not be // intercepted. // Configure modifiers. configure("/configure", m) // Verify assertions. vh := verify.NewHandler() vh.SetRequestVerifier(m) vh.SetResponseVerifier(m) configure("/verify", vh) // Reset verifications. rh := verify.NewResetHandler() rh.SetRequestVerifier(m) rh.SetResponseVerifier(m) configure("/verify/reset", rh) l, err := net.Listen("tcp", *addr) if err != nil { log.Fatal(err) } if *trafficShaping { tsl := trafficshape.NewListener(l) tsh := trafficshape.NewHandler(tsl) configure("/shape-traffic", tsh) l = tsl } log.Println("martian: proxy started on:", l.Addr()) go p.Serve(l) sigc := make(chan os.Signal, 1) signal.Notify(sigc, os.Interrupt, os.Kill) <-sigc log.Println("martian: shutting down") }
func TestIntegration(t *testing.T) { proxy := martian.NewProxy(nil) proxy.RoundTripper = martian.RoundTripFunc(func(req *http.Request) (*http.Response, error) { return proxyutil.NewResponse(200, nil, req), nil }) m := NewModifier() proxy.SetRequestModifier(m) proxy.SetResponseModifier(m) mux := http.NewServeMux() mux.Handle("/martian/modifiers", m) mux.Handle("/", proxy) s := httptest.NewServer(mux) defer s.Close() msg := []byte(` { "header.Modifier": { "scope": ["request", "response"], "name": "Martian-Test", "value": "true" } }`) req, err := http.NewRequest("POST", s.URL+"/martian/modifiers", bytes.NewBuffer(msg)) if err != nil { t.Fatalf("http.NewRequest(): got %v, want no error", err) } req.Header.Set("Content-Type", "application/json") u, err := url.Parse(s.URL) if err != nil { t.Fatalf("url.Parse(%s): got %v, want no error", s.URL, err) } transport := &http.Transport{ Proxy: http.ProxyURL(u), } res, err := transport.RoundTrip(req) if err != nil { t.Fatalf("transport.RoundTrip(%s): got %v, want no error", req.URL, err) } res.Body.Close() if got, want := res.StatusCode, 200; got != want { t.Fatalf("res.StatusCode: got %d, want %d", got, want) } url := "http://example.com" req, err = http.NewRequest("GET", url, nil) if err != nil { t.Fatalf("http.NewRequest(..., %q, nil): got %v, want no error", url, err) } req.Header.Set("Connection", "close") res, err = transport.RoundTrip(req) if err != nil { t.Fatalf("transport.RoundTrip(%q): got %v, want no error", url, err) } res.Body.Close() if got, want := res.Header.Get("Martian-Test"), "true"; got != want { t.Errorf("res.Header.Get(%q): got %q, want %q", "Martian-Test", got, want) } }
func TestIntegration(t *testing.T) { ptr := martiantest.NewTransport() proxy := martian.NewProxy() defer proxy.Close() proxy.SetRoundTripper(ptr) l, err := net.Listen("tcp", "[::1]:0") if err != nil { t.Fatalf("net.Listen(): got %v, want no error", err) } go proxy.Serve(l) m := NewModifier() proxy.SetRequestModifier(m) proxy.SetResponseModifier(m) mux := http.NewServeMux() mux.Handle("/", m) s := httptest.NewServer(mux) defer s.Close() body := strings.NewReader(`{ "header.Modifier": { "scope": ["request", "response"], "name": "Martian-Test", "value": "true" } }`) res, err := http.Post(s.URL, "application/json", body) if err != nil { t.Fatalf("http.Post(%s): got %v, want no error", s.URL, err) } res.Body.Close() if got, want := res.StatusCode, 200; got != want { t.Fatalf("res.StatusCode: got %d, want %d", got, want) } tr := &http.Transport{ Proxy: http.ProxyURL(&url.URL{ Scheme: "http", Host: l.Addr().String(), }), } defer tr.CloseIdleConnections() req, err := http.NewRequest("GET", "http://example.com", nil) if err != nil { t.Fatalf("http.NewRequest(): got %v, want no error", err) } req.Header.Set("Connection", "close") res, err = tr.RoundTrip(req) if err != nil { t.Fatalf("transport.RoundTrip(%q): got %v, want no error", req.URL, err) } res.Body.Close() if got, want := res.Header.Get("Martian-Test"), "true"; got != want { t.Errorf("res.Header.Get(%q): got %q, want %q", "Martian-Test", got, want) } }
// StartWithCertificate runs a proxy on addr and configures a cert for MITM func StartWithCertificate(proxyAddr string, cert string, key string) (*Martian, error) { flag.Set("logtostderr", "true") signal.Ignore(syscall.SIGPIPE) l, err := net.Listen("tcp", proxyAddr) if err != nil { return nil, err } mlog.Debugf("mobileproxy: started listener: %v", l.Addr()) p := martian.NewProxy() mux := http.NewServeMux() p.SetMux(mux) if cert != "" && key != "" { tlsc, err := tls.X509KeyPair([]byte(cert), []byte(key)) if err != nil { log.Fatal(err) } mlog.Debugf("mobileproxy: loaded cert and key") x509c, err := x509.ParseCertificate(tlsc.Certificate[0]) if err != nil { log.Fatal(err) } mlog.Debugf("mobileproxy: parsed cert") mc, err := mitm.NewConfig(x509c, tlsc.PrivateKey) if err != nil { log.Fatal(err) } mc.SetValidity(12 * time.Hour) mc.SetOrganization("Martian Proxy") p.SetMITM(mc) mux.Handle("martian.proxy/authority.cer", martianhttp.NewAuthorityHandler(x509c)) mlog.Debugf("mobileproxy: install cert from http://martian.proxy/authority.cer") } stack, fg := httpspec.NewStack("martian.mobileproxy") p.SetRequestModifier(stack) p.SetResponseModifier(stack) // add HAR logger hl := har.NewLogger() stack.AddRequestModifier(hl) stack.AddResponseModifier(hl) m := martianhttp.NewModifier() fg.AddRequestModifier(m) fg.AddResponseModifier(m) mlog.Debugf("mobileproxy: set martianhttp modifier") // Proxy specific handlers. // These handlers take precendence over proxy traffic and will not be intercepted. // Retrieve HAR logs mux.Handle("martian.proxy/logs", har.NewExportHandler(hl)) mux.Handle("martian.proxy/logs/reset", har.NewResetHandler(hl)) // Update modifiers. mux.Handle("martian.proxy/configure", m) mlog.Debugf("mobileproxy: configure with requests to http://martian.proxy/configure") // Verify assertions. vh := verify.NewHandler() vh.SetRequestVerifier(m) vh.SetResponseVerifier(m) mux.Handle("martian.proxy/verify", vh) mlog.Debugf("mobileproxy: check verifications with requests to http://martian.proxy/verify") // Reset verifications. rh := verify.NewResetHandler() rh.SetRequestVerifier(m) rh.SetResponseVerifier(m) mux.Handle("martian.proxy/verify/reset", rh) mlog.Debugf("mobileproxy: reset verifications with requests to http://martian.proxy/verify/reset") go p.Serve(l) mlog.Infof("mobileproxy: started proxy on listener") return &Martian{ proxy: p, listener: l, mux: mux, }, nil }