Beispiel #1
0
func (m *HttpTampererSymptom) MuckRequest(ctx *muxy.Context) {

	// Body
	if m.Request.Body != "" {
		newreq, err := http.NewRequest(ctx.Request.Method, ctx.Request.URL.String(), bytes.NewBuffer([]byte(m.Request.Body)))
		if err != nil {
			log.Error(err.Error())
		}
		*ctx.Request = *newreq
		log.Debug("Spoofing HTTP Request Body with %s", log.Colorize(log.BLUE, m.Request.Body))
	}

	// Set Cookies
	for _, c := range m.Request.Cookies {
		c.Expires = stringToDate(c.RawExpires)
		log.Debug("Spoofing Request Cookie %s => %s", log.Colorize(log.LIGHTMAGENTA, c.Name), c.String())
		ctx.Request.Header.Add("Cookie", c.String())
	}

	// Set Headers
	for k, v := range m.Request.Headers {
		key := strings.ToTitle(strings.Replace(k, "_", "-", -1))
		log.Debug("Spoofing Request Header %s => %s", log.Colorize(log.LIGHTMAGENTA, key), v)
		ctx.Request.Header.Set(key, v)
	}

	// This Writes all headers, setting status code - so call this last
	if m.Request.Method != "" {
		ctx.Request.Method = m.Request.Method
	}
}
Beispiel #2
0
func (p *proxy) pipe(src io.Reader, dst io.Writer) {
	// Direction
	islocal := src == p.lconn

	buff := make([]byte, p.packetsize)
	done := false
	for !done {
		n, readErr := src.Read(buff)
		if readErr != nil || n == 0 {
			if !islocal {
				p.err("Read failed '%s'\n", readErr)
			}
			done = true
		}

		b := buff[:n]

		ctx := &muxy.Context{Bytes: b}
		for _, middleware := range p.middleware {
			if islocal {
				middleware.HandleEvent(muxy.EVENT_PRE_DISPATCH, ctx)
			} else {
				middleware.HandleEvent(muxy.EVENT_POST_DISPATCH, ctx)
			}
		}

		n, err := dst.Write(b)
		if err != nil {
			log.Error("Write failed: %s", err.Error())
			p.err("Write failed '%s'\n", err)

			return
		}
		if islocal {
			p.sentBytes += uint64(n)
		} else {
			p.receivedBytes += uint64(n)
		}
	}
}
Beispiel #3
0
func checkHttpServerError(err error) {
	if err != nil {
		log.Error("ListenAndServe error: ", err.Error())
	}
}
Beispiel #4
0
func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	transport := p.Transport
	if transport == nil {
		transport = http.DefaultTransport
	}

	outreq := new(http.Request)
	*outreq = *req // includes shallow copies of maps, but okay

	if closeNotifier, ok := rw.(http.CloseNotifier); ok {
		if requestCanceler, ok := transport.(requestCanceler); ok {
			reqDone := make(chan struct{})
			defer close(reqDone)

			clientGone := closeNotifier.CloseNotify()

			outreq.Body = struct {
				io.Reader
				io.Closer
			}{
				Reader: &runOnFirstRead{
					Reader: outreq.Body,
					fn: func() {
						go func() {
							select {
							case <-clientGone:
								requestCanceler.CancelRequest(outreq)
							case <-reqDone:
							}
						}()
					},
				},
				Closer: outreq.Body,
			}
		}
	}

	p.Director(outreq)
	outreq.Proto = "HTTP/1.1"
	outreq.ProtoMajor = 1
	outreq.ProtoMinor = 1
	outreq.Close = false

	// Remove hop-by-hop headers to the backend.  Especially
	// important is "Connection" because we want a persistent
	// connection, regardless of what the client sent to us.  This
	// is modifying the same underlying map from req (shallow
	// copied above) so we only copy it if necessary.
	copiedHeaders := false
	for _, h := range hopHeaders {
		if outreq.Header.Get(h) != "" {
			if !copiedHeaders {
				outreq.Header = make(http.Header)
				copyHeader(outreq.Header, req.Header)
				copiedHeaders = true
			}
			outreq.Header.Del(h)
		}
	}

	if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
		// If we aren't the first proxy retain prior
		// X-Forwarded-For information as a comma+space
		// separated list and fold multiple headers into one.
		if prior, ok := outreq.Header["X-Forwarded-For"]; ok {
			clientIP = strings.Join(prior, ", ") + ", " + clientIP
		}
		outreq.Header.Set("X-Forwarded-For", clientIP)
	}

	// Fire Pre-dispatch middleware event
	ctx := &muxy.Context{Request: req}
	for _, middleware := range p.Middleware {
		middleware.HandleEvent(muxy.EVENT_PRE_DISPATCH, ctx)
	}
	res, err := transport.RoundTrip(outreq)
	if err != nil {
		log.Error("http: proxy error: %v", err)
		rw.WriteHeader(http.StatusInternalServerError)
		return
	}
	defer res.Body.Close()

	// Fire Post-dispatch middleware event
	ctx = &muxy.Context{req, res, rw, nil}
	for _, middleware := range p.Middleware {
		middleware.HandleEvent(muxy.EVENT_POST_DISPATCH, ctx)
	}

	copyHeader(rw.Header(), res.Header)

	// The "Trailer" header isn't included in the Transport's response,
	// at least for *http.Transport. Build it up from Trailer.
	if len(res.Trailer) > 0 {
		var trailerKeys []string
		for k := range res.Trailer {
			trailerKeys = append(trailerKeys, k)
		}
		rw.Header().Add("Trailer", strings.Join(trailerKeys, ", "))
	}

	rw.WriteHeader(res.StatusCode)
	if len(res.Trailer) > 0 {
		// Force chunking if we saw a response trailer.
		// This prevents net/http from calculating the length for short
		// bodies and adding a Content-Length.
		if fl, ok := rw.(http.Flusher); ok {
			fl.Flush()
		}
	}

	p.copyResponse(rw, res.Body)
	res.Body.Close() // close now, instead of defer, to populate res.Trailer
	copyHeader(rw.Header(), res.Trailer)
}