11use crate :: action:: Action ;
2- use crate :: http:: { Header , Request } ;
2+ use crate :: http:: { Header , Request , TrustedProxies } ;
33use serde:: { Deserialize , Serialize } ;
4+ use std:: net:: IpAddr ;
45use std:: time:: { SystemTime , UNIX_EPOCH } ;
56
67#[ derive( Serialize , Deserialize , Debug , Clone ) ]
@@ -76,12 +77,20 @@ impl Log {
7677 proxy : & str ,
7778 time : u64 ,
7879 client_ip : & str ,
80+ trusted_proxies : Option < & TrustedProxies > ,
7981 ) -> Log {
8082 let mut location = None ;
8183 let mut user_agent = None ;
8284 let mut referer = None ;
8385 let mut content_type = None ;
84- let mut ips = vec ! [ client_ip. to_string( ) ] ;
86+ let mut ips = Vec :: new ( ) ;
87+
88+ match client_ip. parse :: < IpAddr > ( ) {
89+ Ok ( ip) => ips. push ( ip) ,
90+ Err ( e) => {
91+ log:: error!( "cannot parse ip address {}, skipping: {}" , client_ip, e) ;
92+ }
93+ }
8594
8695 for header in & request. headers {
8796 if header. name . to_lowercase ( ) == "user-agent" {
@@ -96,11 +105,39 @@ impl Log {
96105 let forwarded_ips = header. value . split ( ',' ) ;
97106
98107 for forwarded_ip in forwarded_ips {
99- ips. push ( forwarded_ip. trim ( ) . to_string ( ) ) ;
108+ match forwarded_ip. parse :: < IpAddr > ( ) {
109+ Ok ( ip) => ips. push ( ip) ,
110+ Err ( e) => {
111+ log:: error!( "cannot parse ip address {}, skipping: {}" , forwarded_ip, e) ;
112+ }
113+ }
114+ }
115+ }
116+
117+ if header. name . to_lowercase ( ) == "forwarded" {
118+ for ( name, val) in header. value . split ( ';' ) . flat_map ( |val| val. split ( ',' ) ) . flat_map ( |pair| {
119+ let mut items = pair. trim ( ) . splitn ( 2 , '=' ) ;
120+ Some ( ( items. next ( ) ?, items. next ( ) ?) )
121+ } ) {
122+ if name. trim ( ) . to_lowercase ( ) . as_str ( ) == "for" {
123+ let ip = val. trim ( ) . trim_start_matches ( '"' ) . trim_end_matches ( '"' ) . to_string ( ) ;
124+
125+ match ip. parse :: < IpAddr > ( ) {
126+ Ok ( ip) => ips. push ( ip) ,
127+ Err ( e) => {
128+ log:: error!( "cannot parse ip address {}, skipping: {}" , ip, e) ;
129+ }
130+ }
131+ }
100132 }
101133 }
102134 }
103135
136+ let untrusted_ips = match trusted_proxies {
137+ Some ( trusted_proxies) => trusted_proxies. remove_trusted_ips ( ips) ,
138+ None => ips,
139+ } ;
140+
104141 for header in response_headers {
105142 if header. name . to_lowercase ( ) == "location" {
106143 location = Some ( header. value . clone ( ) )
@@ -127,7 +164,7 @@ impl Log {
127164 from,
128165 proxy : proxy. to_string ( ) ,
129166 time,
130- ips : Some ( ips ) ,
167+ ips : Some ( untrusted_ips . iter ( ) . map ( |ip| ip . to_string ( ) ) . collect ( ) ) ,
131168 to : location. unwrap_or_default ( ) ,
132169 }
133170 }
0 commit comments