Hice un servicio de red simple con xinetd que lee una cadena del socket tcp y genera su vista codificada. Binario original (qrencode) solo leyendo stdin.
Funciona bien cuando lo uso con netcat
como echo string | nc <ip> <port>
Pero no responde cuando trato de usarlo a través de la redirección bash tcp.
exec 7<>/dev/tcp/<ip>/<port>
echo string >&7
cat <&7
Espera para siempre. Intenté repetir \004, cat /dev/null en este fd y no tuve suerte.
¿Cómo puedo hacer que funcione?
Respuesta aceptada:
Ese inetd
El servicio o el suyo probablemente esté esperando EOF antes de salir (y luego cerrar la conexión).
Para hacer eso, necesitaría que el cliente apague el lado de envío del socket mientras mantiene abierto el lado de recepción. Eso es lo que nc
hace cuando detecta EOF en su stdin.
El /dev/tcp/host/port
interfaz virtual de bash
(copiado de ksh) no permite eso. Incluso zsh
's ztcp
alternativa más flexible no tiene la capacidad de cerrar conexiones asimétricamente.
En su lugar, podría confiar en un tiempo de espera, pero eso no sería confiable. Así que es mejor seguir confiando en utilidades dedicadas como nc
o socat
(posiblemente con un coproc para tener una interfaz similar), o use un lenguaje de programación con una API de red adecuada (con una interfaz para shutdown()
).
El carácter 0x04 (^D
) solo significa EOF para dispositivos terminales cuando la disciplina de línea está en icanon
modo (implementa un editor de línea crudo). Así que para que funcione tendrías que insertar un pseudo-terminal entre el socket creado por xinetd
y su servicio. Por ejemplo, comenzando con:
socat - exec:'your-service',pty,raw,icanon,echo=0,discard=,lnext=,werase=,kill=,start=,stop=,rprnt=,erase=,fdout=3
en lugar de
your-service
Entonces tendrías que enviar:
printf 'text\n\4' >&7
O:
printf 'text\4\4' >&7
para que su servicio vea el final de la entrada.
Debido a ese editor de líneas, your-service
solo verá la entrada cuando envíe una nueva línea o ^D
caracteres (hemos deshabilitado todos los demás caracteres de edición como werase
, erase
, kill
arriba y el ^C
, ^Z
… el manejo también está deshabilitado como parte de raw
).
Por lo tanto, también podría insertar un preprocesador de entrada que se cierre con ese carácter 0x4 como:
awk -v RS='\4' -v ORS= '{print; exit}' | your-service
(tenga en cuenta que eso awk
no puede ser mawk
como mawk
insiste en no procesar su entrada mientras no reciba un búfer completo o eof).