Exemple #1
0
func (f *Filter) Request(ctx *filters.Context, req *http.Request) (*filters.Context, *http.Request, error) {
	if req.Method != "CONNECT" || !f.Match(req.Host) {
		return ctx, req, nil
	}

	hijacker, ok := ctx.GetResponseWriter().(http.Hijacker)
	if !ok {
		return ctx, nil, fmt.Errorf("%#v does not implments Hijacker", ctx.GetResponseWriter())
	}

	conn, _, err := hijacker.Hijack()
	if err != nil {
		return ctx, nil, fmt.Errorf("http.ResponseWriter Hijack failed: %s", err)
	}

	_, err = io.WriteString(conn, "HTTP/1.1 200 OK\r\n\r\n")
	if err != nil {
		conn.Close()
		return ctx, nil, err
	}

	glog.Infof("%s \"STRIP %s %s %s\" - -", req.RemoteAddr, req.Method, req.Host, req.Proto)

	cert, err := f.issue(req.Host)
	if err != nil {
		conn.Close()
		return ctx, nil, err
	}

	tlsConfig := &tls.Config{
		Certificates: []tls.Certificate{*cert},
		ClientAuth:   tls.VerifyClientCertIfGiven,
	}
	tlsConn := tls.Server(conn, tlsConfig)

	if err := tlsConn.Handshake(); err != nil {
		conn.Close()
		return ctx, nil, err
	}

	if ln1, ok := ctx.GetListener().(httpproxy.Listener); ok {
		ln1.Add(tlsConn)
		ctx.SetHijacked(true)
		return ctx, nil, nil
	}

	loConn, err := net.Dial("tcp", ctx.GetListener().Addr().String())
	if err != nil {
		return ctx, nil, err
	}

	go httpproxy.IoCopy(loConn, tlsConn)
	go httpproxy.IoCopy(tlsConn, loConn)

	ctx.SetHijacked(true)
	return ctx, nil, nil
}