i'm writing a sort of tool to analyse traffic that goes to nginx on my server by logging them into a database, then perform certain actions on them. i've decided the best way to do this would be to analyse the access_log
, because i'll be able to see all the requests in there. rather than continuously reading the log file, which i'd have to parse, i thought i'd use nginx's syslog feature. i wrote this line in my nginx.conf
:
access_log syslog:server=unix:/run/user/1000/logtool.sock,severity=info combined;
and ran my rust program. i saw no connections in my rust program, so checked the nginx.log
, and saw this:
2025/05/10 13:00:03 [alert] 40303#40303: connect() failed (91: Protocol wrong type for socket) while logging to syslog, server: unix:/run/user/1000/logtool.sock
why is that? am i opening the socket wrong? this is the code i used:
use std::io::prelude::*;
use std::os::unix::net::{UnixListener, UnixStream};
fn handle_client(mut socket: UnixStream) -> std::io::Result<()> {
let addr = socket.peer_addr();
println!("a client ({addr:?}) connected");
loop {
let mut buf = Vec::new();
let amt = socket.read_to_end(&mut buf)?;
if amt == 0 {
println!("the client {addr:?} disconnected");
break;
}
dbg!(buf);
}
Ok(())
}
fn main() -> std::io::Result<()> {
let socket_path = format!(
"{}/logtool.sock",
std::env::var("XDG_RUNTIME_DIR").unwrap_or("/tmp".to_string())
);
let _ = std::fs::remove_file(&socket_path);
let listener = UnixListener::bind(socket_path)?;
loop {
for stream in listener.incoming() {
match stream {
Ok(socket) => handle_client(socket)?,
Err(err) => eprintln!("cannot accept connection: {err:?}"),
}
}
}
}
i have also used the .accept()
method of doing it instead of .incoming()
, but the same thing happens. how do i fix this problem?
nginx expects a datagram socket, not a stream socket. you can create a datagram socket like this:
use std::os::unix::net::UnixDatagram;
fn main() -> std::io::Result<()> {
let socket_path = format!(
"{}/logtool.sock",
std::env::var("XDG_RUNTIME_DIR").unwrap_or("/tmp".to_string())
);
let _ = std::fs::remove_file(&socket_path);
let listener = UnixDatagram::bind(socket_path)?;
loop {
let mut buf = vec![0; 1_024];
let read = listener.recv(&mut buf)?;
let buf = &buf[..read];
dbg!(buf);
}
}