diff --git a/src/extensions/accesscontrol.ml b/src/extensions/accesscontrol.ml index 2fc848f63..c211dfd69 100644 --- a/src/extensions/accesscontrol.ml +++ b/src/extensions/accesscontrol.ml @@ -39,17 +39,19 @@ let ip s = in fun ri -> let r = - match Ocsigen_request.remote_ip_parsed ri with - | `Ip ip -> Ipaddr.Prefix.mem ip prefix - | `Unix _ -> false + match Ocsigen_request.client_conn ri with + | `Inet (ip, _) -> Ipaddr.Prefix.mem ip prefix + | _ -> false in if r then Logs.info ~src:section (fun fmt -> - fmt "IP: %s matches %s" (Ocsigen_request.remote_ip ri) s) + fmt "IP: %s matches %s" (Ocsigen_request.client_conn_to_string ri) s) else Logs.info ~src:section (fun fmt -> - fmt "IP: %s does not match %s" (Ocsigen_request.remote_ip ri) s); + fmt "IP: %s does not match %s" + (Ocsigen_request.client_conn_to_string ri) + s); r let port port ri = @@ -222,22 +224,22 @@ let allow_forward_for_handler ?(check_equal_ip = false) () = let last_proxy = List.last proxies in let proxy_ip = Ipaddr.of_string_exn last_proxy in let equal_ip = - match Ocsigen_request.remote_ip_parsed request_info with - | `Ip r_ip -> Ipaddr.compare proxy_ip r_ip = 0 - | `Unix _ -> false + match Ocsigen_request.client_conn request_info with + | `Inet (r_ip, _) -> Ipaddr.compare proxy_ip r_ip = 0 + | _ -> false in if equal_ip || not check_equal_ip then { request with Ocsigen_extensions.request_info = Ocsigen_request.update ~forward_ip:proxies - ~remote_ip:original_ip request_info } + ~client_conn:(`Forwarded_for original_ip) request_info } else ( (* the announced ip of the proxy is not its real ip *) Logs.warn ~src:section (fun fmt -> fmt "X-Forwarded-For: host ip (%s) does not match the header (%s)" - (Ocsigen_request.remote_ip request_info) + (Ocsigen_request.client_conn_to_string request_info) header); request) | _ -> diff --git a/src/extensions/revproxy.ml b/src/extensions/revproxy.ml index 1ad47fa42..9554f0bac 100644 --- a/src/extensions/revproxy.ml +++ b/src/extensions/revproxy.ml @@ -109,7 +109,7 @@ let gen dir = function (Ocsigen_request.address request_info) in String.concat ", " - (Ocsigen_request.remote_ip request_info + (Ocsigen_request.client_conn_to_string request_info :: Ocsigen_request.forward_ip request_info @ [address]) in diff --git a/src/server/ocsigen_cohttp.ml b/src/server/ocsigen_cohttp.ml index c0e79fed5..cd152f01f 100644 --- a/src/server/ocsigen_cohttp.ml +++ b/src/server/ocsigen_cohttp.ml @@ -57,15 +57,13 @@ end let handler ~ssl ~address ~port ~connector (flow, conn) request body = let filenames = ref [] in let edn = Conduit_lwt_unix.endp_of_flow flow in - let rec getsockname = function - | `TCP (ip, port) -> Unix.ADDR_INET (Ipaddr_unix.to_inet_addr ip, port) - | `Unix_domain_socket path -> Unix.ADDR_UNIX path - | `TLS (_, edn) -> getsockname edn - | `Unknown err -> raise (Failure ("resolution failed: " ^ err)) - | `Vchan_direct _ -> raise (Failure "VChan not supported") - | `Vchan_domain_socket _ -> raise (Failure "VChan not supported") + let client_conn = + match edn with + | `TCP (ip, port) | `TLS (_, `TCP (ip, port)) -> `Inet (ip, port) + | `Unix_domain_socket path | `TLS (_, `Unix_domain_socket path) -> + `Unix path + | _ -> `Unknown in - let sockaddr = getsockname edn in let connection_closed = try fst (Hashtbl.find connections conn) with Not_found -> @@ -110,7 +108,7 @@ let handler ~ssl ~address ~port ~connector (flow, conn) request body = in (* TODO: equivalent of Ocsigen_range *) let request = - Ocsigen_request.make ~address ~port ~ssl ~filenames ~sockaddr ~body + Ocsigen_request.make ~address ~port ~ssl ~filenames ~client_conn ~body ~connection_closed request in Lwt.finalize @@ -120,7 +118,7 @@ let handler ~ssl ~address ~port ~connector (flow, conn) request body = (match Ocsigen_request.host request with | None -> "" | Some h -> h) - (Ocsigen_request.remote_ip request) + (Ocsigen_request.client_conn_to_string request) (Option.value ~default:"" (Ocsigen_request.header request Ocsigen_header.Name.user_agent)) (Option.fold ~none:"" diff --git a/src/server/ocsigen_request.ml b/src/server/ocsigen_request.ml index 040662272..627c0fa49 100644 --- a/src/server/ocsigen_request.ml +++ b/src/server/ocsigen_request.ml @@ -48,14 +48,18 @@ let make_uri u = and u_get_params_flat = lazy (flatten_get_params (Lazy.force u_get_params)) in {u_uri; u_get_params; u_get_params_flat; u_path; u_path_string} +type client_conn = + [ `Inet of Ipaddr.t * int + | `Unix of string + | `Forwarded_for of string + | `Unknown ] + type t = { r_address : Ocsigen_config.Socket_type.t ; r_port : int ; r_ssl : bool ; r_filenames : string list ref - ; r_sockaddr : Lwt_unix.sockaddr - ; r_remote_ip : string Lazy.t - ; r_remote_ip_parsed : [`Ip of Ipaddr.t | `Unix of string] Lazy.t + ; r_client_conn : client_conn ; r_forward_ip : string list ; r_uri : uri ; r_meth : Cohttp.Code.meth @@ -81,31 +85,16 @@ let make ~port ~ssl ~filenames - ~sockaddr + ~client_conn ~body ~connection_closed request = - let r_remote_ip = - lazy - (match sockaddr with - | Unix.ADDR_INET (ip, _port) -> Unix.string_of_inet_addr ip - | ADDR_UNIX f -> f) - in - let r_remote_ip_parsed = - lazy - (match sockaddr with - | Unix.ADDR_INET (ip, _port) -> - `Ip (Ipaddr.of_string_exn (Unix.string_of_inet_addr ip)) - | ADDR_UNIX f -> `Unix f) - in { r_address = address ; r_port = port ; r_ssl = ssl ; r_filenames = filenames - ; r_sockaddr = sockaddr - ; r_remote_ip - ; r_remote_ip_parsed + ; r_client_conn = client_conn ; r_forward_ip = forward_ip ; r_uri = make_uri (Cohttp.Request.uri request) ; r_encoding = Cohttp.Request.encoding request @@ -127,7 +116,7 @@ let path {r_uri = {u_path; _}; _} = Lazy.force u_path let update ?ssl ?forward_ip - ?remote_ip + ?client_conn ?sub_path ?meth ?get_params_flat @@ -139,8 +128,7 @@ let update ; r_uri = {u_uri; _} as r_uri ; r_meth ; r_forward_ip - ; r_remote_ip - ; r_remote_ip_parsed + ; r_client_conn ; r_cookies_override ; r_body ; r_sub_path @@ -150,11 +138,8 @@ let update let r_ssl = match ssl with Some ssl -> ssl | None -> r_ssl and r_forward_ip = match forward_ip with Some forward_ip -> forward_ip | None -> r_forward_ip - and r_remote_ip, r_remote_ip_parsed = - match remote_ip with - | Some remote_ip -> - lazy remote_ip, lazy (`Ip (Ipaddr.of_string_exn remote_ip)) - | None -> r_remote_ip, r_remote_ip_parsed + and r_client_conn = + match client_conn with Some c -> c | None -> r_client_conn and r_sub_path = match sub_path with Some _ -> sub_path | None -> r_sub_path and r_body = match post_data with @@ -192,8 +177,7 @@ let update ; r_uri ; r_meth ; r_forward_ip - ; r_remote_ip - ; r_remote_ip_parsed + ; r_client_conn ; r_body ; r_cookies_override ; r_sub_path @@ -292,8 +276,15 @@ let post_params r s i = let files r s i = match force_post_data r s i with Some v -> Some (v >|= snd) | None -> None -let remote_ip {r_remote_ip; _} = Lazy.force r_remote_ip -let remote_ip_parsed {r_remote_ip_parsed; _} = Lazy.force r_remote_ip_parsed +let client_conn {r_client_conn = c; _} = c + +let client_conn_to_string {r_client_conn = c; _} = + match c with + | `Inet (ip, _) -> Ipaddr.to_string ip + | `Unix path -> "unix:" ^ path + | `Forwarded_for ip -> "forwarded:" ^ ip + | `Unknown -> "unknown" + let forward_ip {r_forward_ip; _} = r_forward_ip let request_cache {r_request_cache; _} = r_request_cache let tries {r_tries; _} = r_tries diff --git a/src/server/ocsigen_request.mli b/src/server/ocsigen_request.mli index 4d9db6004..4c7dbee6b 100644 --- a/src/server/ocsigen_request.mli +++ b/src/server/ocsigen_request.mli @@ -9,6 +9,15 @@ type file_info = Ocsigen_multipart.file_info = type post_data = (string * string) list * (string * file_info) list +type client_conn = + [ `Inet of Ipaddr.t * int + | `Unix of string + | `Forwarded_for of string + | `Unknown ] +(** Type of connection used by the client. [`Inet] means the client connected + through the Internet. [`Forwarded_for] means that the client connected + through a proxy and carries the IP address reported in the HTTP headers. *) + val make : ?forward_ip:string list -> ?sub_path:string @@ -19,7 +28,7 @@ val make : -> port:int -> ssl:bool -> filenames:string list ref - -> sockaddr:Lwt_unix.sockaddr + -> client_conn:client_conn -> body:Cohttp_lwt.Body.t -> connection_closed:unit Lwt.t -> Cohttp.Request.t @@ -28,7 +37,7 @@ val make : val update : ?ssl:bool -> ?forward_ip:string list - -> ?remote_ip:string + -> ?client_conn:client_conn -> ?sub_path:string -> ?meth:Cohttp.Code.meth -> ?get_params_flat:(string * string) list @@ -74,8 +83,13 @@ val post_params : -> Int64.t option -> (string * string) list Lwt.t option -val remote_ip : t -> string -val remote_ip_parsed : t -> [`Ip of Ipaddr.t | `Unix of string] +val client_conn : t -> client_conn +(** The way the client connects to the server (for example, its IP address if + connected over the internet). *) + +val client_conn_to_string : t -> string +(** A textual representation of [client_conn] suitable for use in logs. *) + val forward_ip : t -> string list val content_type : t -> content_type option val request_cache : t -> Polytables.t diff --git a/test/extensions/deflatemod.t/run.t b/test/extensions/deflatemod.t/run.t index 663578ec8..b72a88677 100644 --- a/test/extensions/deflatemod.t/run.t +++ b/test/extensions/deflatemod.t/run.t @@ -1,14 +1,14 @@ $ source ../../server-test-helpers.sh $ run_server ./test.exe ocsigen:main: [WARNING] Command pipe created - ocsigen:access: connection for local-test from (): /index.html + ocsigen:access: connection for local-test from unix: (): /index.html ocsigen:ext: [INFO] host found! local-test:0 matches .* ocsigen:ext:staticmod: [INFO] Is it a static file? ocsigen:local-file: [INFO] Testing "./index.html". ocsigen:local-file: [INFO] checking if file index.html can be sent ocsigen:ext: [INFO] Compiling exclusion regexp $^ ocsigen:local-file: [INFO] Returning "./index.html". - ocsigen:access: connection for local-test from (): /index.html + ocsigen:access: connection for local-test from unix: (): /index.html ocsigen:ext: [INFO] host found! local-test:0 matches .* ocsigen:ext:staticmod: [INFO] Is it a static file? ocsigen:local-file: [INFO] Testing "./index.html".