Linux/Unix Socket Self-connection
We can simple reproduce this phenomenon with the following python program
import socket
for i in range(65536):
try:
s = socket.create_connection(('127.0.0.1', 50000))
print 'connected to {0}'.format(s.getpeername())
except Exception as e:
pass
when we try to connect some socket in the same host. if we don't bind your client to a specific port, operating system will provide ephemeral port
for you. if it's happened to be the one you want to connect to. it causes self connection. Make sure the port you are trying to connect is in /proc/sys/net/ipv4/ip_local_port_range
Can one reliably connect a TCP socket to itself?
The most straightforward approach would be to bind to the loopback adapter. Just listen to 127.0.0.1
on some arbitrary port and the connect to that.
The problem with this approach is that the port is global on the machine, so that means other programs can connect to it too, and if you have multiple programs you might run into conflicts or conceivably exhaust all the possible ports.
Another approach is to use Unix domain sockets, but this is not supported on Windows.
TCP simultaneous open and self connect prevention
For server you need to bind() socket to port. Once addr:port pair had socket bound, it will no longer be used for implicit binding in connect().
No problem, no trouble.
Identify program that connects to a Unix Domain Socket
Yes, this is possible on Linux, but it won't be very portable. It's achieved using what is called "ancillary data" with sendmsg
/ recvmsg
.
- Use
SO_PASSCRED
withsetsockopt
- Use
SCM_CREDENTIALS
and thestruct ucred
structure
This structure is defined in Linux:
struct ucred {
pid_t pid; /* process ID of the sending process */
uid_t uid; /* user ID of the sending process */
gid_t gid; /* group ID of the sending process */
};
Note you have to fill these in your msghdr.control
, and the kernel will check if they're correct.
The main portability hindrance is that this structure differs on other Unixes - for example on FreeBSD it's:
struct cmsgcred {
pid_t cmcred_pid; /* PID of sending process */
uid_t cmcred_uid; /* real UID of sending process */
uid_t cmcred_euid; /* effective UID of sending process */
gid_t cmcred_gid; /* real GID of sending process */
short cmcred_ngroups; /* number or groups */
gid_t cmcred_groups[CMGROUP_MAX]; /* groups */
};
unix socket creation then fork(), messaging gets mixed up
I did some additional research and there is another way to do this, I learned about pthread_atfork() which sets up functions to be called by the parent and the child upon fork.. i actually used this mechanism to stop and start the network functionality on the child, and it worked!
https://linux.die.net/man/3/pthread_atfork
Calling open() on a Unix domain socket failed with error No such device or address
The /tmp/pipe1
is not a pipe file. It's a socket file. That's what the leading s
means in srwxr-xr-x
.
And Bash's redirection like >
does not support socket files. You need to use socket API to open the file.
With strace (e.g. strace bash -c 'echo > /tmp/sockfile'
) we can see:
...
openat(AT_FDCWD, "/tmp/sockfile", ...) = -1 ENXIO (No such device or address)
...
So the error code is ENXIO
whose corresponding error message is No such device or address
. Bash is just calling standard C API (like strerror) to print the error.
Exampe code for client side:
int
sock_connect(char * sockpath)
{
int sock_fd;
struct sockaddr_un srv_addr = { 0 };
sock_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
if (sock_fd < 0) {
return -1;
}
srv_addr.sun_family = AF_LOCAL;
snprintf(srv_addr.sun_path, sizeof(srv_addr.sun_path), "%s", sockpath);
if (connect(sock_fd, (struct sockaddr *) & srv_addr, sizeof(srv_addr)) < 0) {
return -1;
}
return sock_fd;
}
HTTP over AF_UNIX: HTTP connection to unix socket
So long as your socket is a stream socket (SOCK_STREAM
rather than SOCK_DGRAM
) then it's technically possible. There's nothing in HTTP that requires TCP/IP, it just requires a reliable bidirectional stream.
However I've never seen an HTTP client that knows how to connect to such a socket. There's no URL format that I know of that would work, should you actually need to use a URL to talk to the server.
Also note that some things that normal web servers depend on (such as getpeername()
, to identify the client) make no sense when you're not using TCP/IP.
EDIT I just saw your edit about mapping localhost
to the UNIX socket. This is perfectly feasible, you just need to ensure that the client knows how to find the path of the UNIX socket that should be used instead of connecting to 127.0.0.1:xxx
Related Topics
How to View Dask Dashboard When Running on a Virtual Machine
How to Give Password in Shell Script
What Is The Most Efficient Way to Exchange High Volume Data Between 2 Process
How to Start a Nodejs Process on a Remote Server
Alternative to Valgrind (Memcheck) for Finding Leaks on Linux
How to Test My Bash Script on Older Versions of Bash
Linux Script with Netcat Stops Working After X Hours
How to Manage Permissions When Developing in a Docker Container
How to Set Folder Permissions for a Particular Container on Elastic Beanstalk
How Does Linux Kernel Creates Sysfs
Upgrading PHPmyadmin (And Other Packages) on Debian Squeeze
Using Linux Virtual Mouse Driver
What Happens Internally When Deleting an Opened File in Linux
Put Command Output into String
How to Stop Sed from Buffering
Why Doesn't Time() from Time.H Have a Syscall to Sys_Time
What Are Best Parameters to Run Imagemagick to Convert Low Quality PDF to Images (For Ocr)