예제 #1
0
func defaultIcap(w icap.ResponseWriter, req *icap.Request) {
	h := w.Header()
	h.Set("ISTag", ISTag)
	h.Set("Service", "SquidBlocker default ICAP service")

	if *debug {
		fmt.Fprintln(os.Stderr, "Printing the full ICAP request")
		fmt.Fprintln(os.Stderr, req)
		fmt.Fprintln(os.Stderr, req.Request)
	}
	switch req.Method {
	case "OPTIONS":
		h.Set("Methods", "REQMOD, RESPMOD")
		h.Set("Options-TTL", "1800")
		h.Set("Allow", "204")
		h.Set("Preview", "0")
		h.Set("Transfer-Preview", "*")
		h.Set("Max-Connections", "4000")
		h.Set("This-Server", "Default ICAP url which bypass all requests adaptation")
		h.Set("X-Include", "X-Client-IP, X-Authenticated-Groups, X-Authenticated-User, X-Subscriber-Id, X-Server-IP")
		w.WriteHeader(200, nil, false)
	case "REQMOD":
		if *debug {
			fmt.Fprintln(os.Stderr, "Default REQMOD, you should use the apropriate ICAP URL")
		}
		w.WriteHeader(204, nil, false)
	case "RESPMOD":
		if *debug {
			fmt.Fprintln(os.Stderr, "Default RESPMOD, you should use the apropriate ICAP URL")
		}
		w.WriteHeader(204, nil, false)
	default:
		w.WriteHeader(405, nil, false)
		if *debug {
			fmt.Fprintln(os.Stderr, "Invalid request method")
		}
	}
}
예제 #2
0
func filterByUrl(w icap.ResponseWriter, req *icap.Request) {
	h := w.Header()
	h.Set("ISTag", ISTag)
	h.Set("Service", "SquidBlocker filter ICAP service")

	if *debug {
		fmt.Fprintln(os.Stderr, "Printing the full ICAP request")
		fmt.Fprintln(os.Stderr, req)
		fmt.Fprintln(os.Stderr, req.Request)
	}
	switch req.Method {
	case "OPTIONS":
		h.Set("Methods", "REQMOD, RESPMOD")
		h.Set("Options-TTL", "1800")
		h.Set("Allow", "204")
		h.Set("Preview", "0")
		h.Set("Transfer-Preview", "*")
		h.Set("Max-Connections", "4000")
		h.Set("X-Include", "X-Client-IP, X-Authenticated-Groups, X-Authenticated-User, X-Subscriber-Id")
		w.WriteHeader(200, nil, false)
	case "REQMOD":

		// Check if the method is either OPTIONS\GET\POST\PUT etc
		// Also to analyse the request stucutre to verify what is the current one used
		// based on the RFC section at: http://tools.ietf.org/html/rfc7230#section-5.3
		// Treat the CONNECT method in a special way due to the fact that it cannot actually be modified.
		checkhost := ""
		port := "0"
		answer := *defaultAnswer
		var err error
		if *debug {
			fmt.Fprintln(os.Stderr, "Default CASE. Request to host: "+req.Request.URL.Host+", Request Method: "+req.Request.Method)
			fmt.Fprintln(os.Stderr, "The full url from the ICAP client request: "+req.Request.URL.String())
		}

		checkhost, port, err = net.SplitHostPort(req.Request.URL.Host)
		if err != nil {
			_ = err
			checkhost = req.Request.URL.Host
		}

		if port != "0" {
			if *debug {
				fmt.Fprintln(os.Stderr, "Rquest with port: "+port)
			}
		}

		if req.Request.Method == "CONNECT" && len(checkhost) > 0 && port != "0" {
			answer = check_tcp(checkhost, port)
		} else {
			answer = check(req.Request.URL.String())
		}

		if *debug {
			fmt.Fprintln(os.Stderr, "ERRlog: reporting answer size => "+strconv.Itoa(len(answer)))
			fmt.Fprintln(os.Stderr, "ERRlog: reporitng answer => "+answer+", for =>"+req.Request.URL.String())
		}

		// The next part comes to make sure that a DUNO respnse will be handled as the default answer/action
		if strings.HasPrefix(answer, "DUNO") {
			answer = *defaultAnswer + " rate=100 default_answer=yes"
			if *debug {
				fmt.Fprintln(os.Stderr, "ERRlog: reporting answer startsWith => \"DUNO\", taking default action")
				if len(*defaultAnswer) > 0 {
					fmt.Fprintln(os.Stderr, req.Request.URL.String()+" "+*defaultAnswer+" rate=40 default_answer=yes")
				} else {
					fmt.Fprintln(os.Stderr, req.Request.URL.String()+" OK state=DUNO")
				}
			}
		}

		if strings.HasPrefix(answer, "OK") {
			if *debug {
				fmt.Fprintln(os.Stderr, "OK response and sending 204 back")
			}
			w.WriteHeader(204, nil, false)
			return
		}
		if strings.HasPrefix(answer, "ERR") {
			if *debug {
				fmt.Fprintln(os.Stderr, "ERR response and sending 307 redirection back")
			}
			resp := new(http.Response)
			resp.Status = "307 SquidBlocker this url has been filtered!"
			resp.StatusCode = 307
			resp.Proto = "HTTP/1.1"
			resp.ProtoMajor = 1
			resp.ProtoMinor = 1
			myMap := make(map[string][]string)
			//What if it is a connect request
			myMap["Location"] = append(myMap["Location"], *block_page+"?url="+url.QueryEscape(req.Request.URL.String()))
			resp.Header = myMap
			//resp.Body = ioutil.NopCloser(bytes.NewBufferString(body))
			//resp.ContentLength = int64(len(body))
			resp.Request = req.Request
			w.WriteHeader(200, resp, true)
			return
		}
		if *debug {
			fmt.Fprintln(os.Stderr, "Unknown asnwer and scenario, not adapting the request")
		}
		w.WriteHeader(204, nil, false)
		return
	case "RESPMOD":
		w.WriteHeader(204, nil, false)
	default:
		w.WriteHeader(405, nil, false)
		if *debug {
			fmt.Fprintln(os.Stderr, "Invalid request method")
		}
	}
}