|
|
|
|
@ -1,7 +1,9 @@
|
|
|
|
|
use httparse;
|
|
|
|
|
use std::io::prelude::*;
|
|
|
|
|
use std::net::{TcpListener, TcpStream};
|
|
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
|
println!("Replying with most probable peer's ip on port 7878");
|
|
|
|
|
let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
|
|
|
|
|
|
|
|
|
|
for stream in listener.incoming() {
|
|
|
|
|
@ -11,6 +13,8 @@ fn main() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reply to TCP streem with peer's IP
|
|
|
|
|
// if anyhting goes wrong, just slap 404 on it
|
|
|
|
|
fn handle_connection(mut stream: TcpStream) {
|
|
|
|
|
// make it 8k?
|
|
|
|
|
// https://stackoverflow.com/questions/686217/maximum-on-http-header-values
|
|
|
|
|
@ -18,20 +22,33 @@ fn handle_connection(mut stream: TcpStream) {
|
|
|
|
|
stream.read(&mut buffer).unwrap();
|
|
|
|
|
|
|
|
|
|
let get = b"GET / HTTP";
|
|
|
|
|
|
|
|
|
|
let (status_line, contents) = if buffer.starts_with(get) {
|
|
|
|
|
(
|
|
|
|
|
"HTTP/1.1 200 OK",
|
|
|
|
|
stream.peer_addr().unwrap().ip().to_string(),
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
(
|
|
|
|
|
let err404 = (
|
|
|
|
|
"HTTP/1.1 404 NOT FOUND",
|
|
|
|
|
"<html>\n<head><title>404 Not Found</title></head>\n\
|
|
|
|
|
<body bgcolor=\"white\">\n<center><h1>404 Not Found</h1></center>\n\
|
|
|
|
|
<hr>\n</body>\n</html>"
|
|
|
|
|
.to_string(),
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// println!("Request: {}", String::from_utf8_lossy(&buffer[..]));
|
|
|
|
|
|
|
|
|
|
let (status_line, contents) = if buffer.starts_with(get) {
|
|
|
|
|
let mut headers = [httparse::EMPTY_HEADER; 30];
|
|
|
|
|
let mut req = httparse::Request::new(&mut headers);
|
|
|
|
|
|
|
|
|
|
match req.parse(&buffer) {
|
|
|
|
|
Ok(_) => {
|
|
|
|
|
let peer_ip =
|
|
|
|
|
pick_ip(req).unwrap_or_else(|| stream.peer_addr().unwrap().ip().to_string());
|
|
|
|
|
("HTTP/1.1 200 OK", peer_ip)
|
|
|
|
|
}
|
|
|
|
|
Err(e) => {
|
|
|
|
|
eprintln!("{:?}", e);
|
|
|
|
|
err404
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
err404
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// add date header formatted to rfc2822?
|
|
|
|
|
@ -49,3 +66,23 @@ fn handle_connection(mut stream: TcpStream) {
|
|
|
|
|
stream.write(response.as_bytes()).unwrap();
|
|
|
|
|
stream.flush().unwrap();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Pick most likely peer ip from request headers
|
|
|
|
|
fn pick_ip(req: httparse::Request) -> Option<String> {
|
|
|
|
|
// https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-
|
|
|
|
|
// CF-Connecting-IP
|
|
|
|
|
// X-Forwarded-For
|
|
|
|
|
let mut ip = None;
|
|
|
|
|
|
|
|
|
|
for header in req.headers {
|
|
|
|
|
let name = header.name.to_lowercase();
|
|
|
|
|
|
|
|
|
|
if name == "CF-Connecting-IP".to_lowercase() {
|
|
|
|
|
ip = Some(String::from_utf8_lossy(header.value).to_string());
|
|
|
|
|
break;
|
|
|
|
|
} else if name == "X-Forwarded-For".to_lowercase() {
|
|
|
|
|
ip = Some(String::from_utf8_lossy(header.value).to_string());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ip
|
|
|
|
|
}
|
|
|
|
|
|