I've made a very basic port-scan program in C to scan a port range. Here it is:
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#define HOST "127.0.0.1"
#define PORT 4444
int createConnection(const char *host[], const int port)
{
struct sockaddr_in addr;
int sock = 0;
int ret;
struct sockaddr_in server_addr;
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
printf("Error %d socket creating.\n", sock);
return -1;
}
else
{
memset(&server_addr, '0', sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
ret = inet_pton(AF_INET, host, &server_addr.sin_addr);
if (ret <= 0)
{
printf("Error %d unsuported address: %d\n", ret);
return -2;
}
else
{
ret = connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0)
{
//printf("[-] Port %d closed.\n", port);
close(sock);
return 1;
}
else
{
printf("[+] Port %d open.\n", port);
close(sock);
return 0;
}
}
}
}
int main(int argc, const char *argv[])
{
for (int i = 1; i < 65536; i++)
{
createConnection("127.0.0.1", i);
}
}
As you can see in the for loop, it scans from port 1 to port 65535. The problem is that when I start it, I get this output:
[+] Port 42178 open.
[+] Port 48650 open.
[+] Port 60078 open.
The "open ports" always change, but are always superior to 40000. But, I checked with netstat -tulpn, only my port 68 is open for the dhclient, which is UDP and not TCP. Why does it say that I have open ports ?
I suspect you're running into your open socket source ports while scanning.
TCP connections have a source port. If one is not assigned to a socket (via bind), then the kernel assigns an ephemeral port (in the high range) to the socket when you call connect, before the SYN is sent.
Since you are connecting your sockets to your local machine, as you loop through the destination ports, it is possible that the kernel will assign a random ephemeral source port that happens to match the same destination port to which you're about to connect.
See:
Linux/Unix Socket Self-connection
Socket getting created with same IP and port on local host
Related
I am working in a simple socket project. I would like to know:
why error messages appear before telnet localhost 5678?
why SO_REUSEADDR (between socket() and bind()) don't work, and what else I should try?
Code Output Message:
bind error
Error opening file: Address already in use
telnet localhost 5678
[+]Server Socket is created.
main.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#define BUFSIZE 1024 // Buffer Size
#define PORT 5678
int main() {
printf("telnet localhost 5678\n");
int rfd; // socket descriptor
int clientfd; // client descriptor
struct sockaddr_in client; // Client Socket address
socklen_t client_len; // Length of Client Data
char input[BUFSIZE]; // Client Data -> Server
int bytes_read; // Client Bytes
// 1. socket() = create a socket, SOCK_STREAM = TCP
rfd = socket(AF_INET, SOCK_STREAM, 0);
if (rfd < 0) {
fprintf(stderr, "socket error\n");
exit(-1);
}
printf("[+]Server Socket is created.\n");
// optional
int enable = 1;
if (setsockopt(rfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
fprintf(stderr, "setsockopt(SO_REUSEADDR) failed");
//Initialize the server address by the port and IP
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET; // Internet address family: v4 address
server.sin_addr.s_addr = INADDR_ANY; // Server IP address
server.sin_port = htons(PORT); // Server port
// 2. bind() = bind the socket to an address
int brt = bind(rfd, (struct sockaddr *) &server, sizeof(server));
if (brt < 0) {
int errnum;
errnum = errno;
fprintf(stderr, "bind error\n");
fprintf(stderr, "Error opening file: %s\n", strerror(errnum));
exit(-1);
}
printf("[+]Bind to port %d\n", PORT);
// 3. listen() = listen for connections
int lrt = listen(rfd, 50);
if (lrt < 0) {
printf("listen error\n");
exit(-1);
}
if (lrt == 0) {
printf("[+]Listening....\n");
}
// non-stop loop
while (1) {
// 4. accept() = accept a new connection on socket from client
clientfd = accept(rfd, (struct sockaddr *) &client, &client_len);
if (clientfd < 0) {
fprintf(stderr, "accept failed with error %d\n");
exit(-1);
}
printf("Client connected\n");
...
close(clientfd);
printf("Client disconnected\n");
}
close(rfd);
}
I'm assuming that you are using Linux. If you want to rebind to an address, you should use SO_REUSEPORT not SO_REUSEADDR. Name is really misleading. But make sure that you know how it works and whether you really want to use it or not.
You can check difference here: How do SO_REUSEADDR and SO_REUSEPORT differ?
I have a C socket that listens on port 1001 on localhost. I also have the client code that connects to port 1001 on the ip 127.0.0.1. If I send the client's code to my friend, how could he have access to my machine when we would be on different networks? Is it possible for me just by changing the server code to make my public IP open for connections on port 1001? Below is the simple server code:
obs: I learning C.
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#define BUFSIZE 256
short SocketCreate(void)
{
short hSocket;
printf("Create the socket\n");
hSocket = socket(AF_INET, SOCK_STREAM, 0);
// close(hSocket);
return hSocket;
}
int BindCreatedSocket(int hSocket)
{
int iRetval = -1, ClientPort = 1001;
struct sockaddr_in remote = {0};
remote.sin_family = AF_INET;
remote.sin_addr.s_addr = htonl(INADDR_ANY);
remote.sin_port = htons(ClientPort);
iRetval = bind(hSocket, (struct sockaddr *)&remote, sizeof(remote));
return iRetval;
}
int main(int argc, char *argv[])
{
int socket_desc, sock, clientLen;
struct sockaddr_in client;
char client_message[200] = {0}, message[9999] = {0};
char buf[BUFSIZE];
socket_desc = SocketCreate();
if (socket_desc == -1)
{
printf("Could not create socket");
return 1;
}
printf("Socket created\n");
if (BindCreatedSocket(socket_desc) < 0)
{
perror("bind failed.");
return 1;
}
printf("Waiting for incoming connections...\n");
listen(socket_desc, 3);
while (1)
{
clientLen = sizeof(struct sockaddr_in);
sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t *)&clientLen);
if (sock < 0)
{
perror("accept failed");
return 1;
}
// printf("Connection accepted\n");
memset(client_message, '\0', sizeof(client_message));
memset(message, '\0', sizeof(message));
if (recv(sock, client_message, 200, 0) < 0)
{
printf("recv failed");
break;
}
if (strcmp(client_message, "exitserver") == 0)
{
close(socket_desc);
close(sock);
break;
}
}
return 0;
}
I have a C socket that listens on port 1001 on localhost. I also have
the client code that connects to port 1001 on the ip 127.0.0.1. If I
send the client's code to my friend, how could he have access to my
machine when we would be on different networks?
They couldn't. Address 127.0.0.1 is a loopback address. Packets sent to that address are always directed to the machine that sent them.
Is it possible for me just by changing the server code to make my
public IP open for connections on port 1001?
Do you have a public IP? 127.0.0.1 certainly isn't one, and most people with consumer-grade internet service don't have one. If you did have one, you probably would have had to make special arrangements to get it, and you would probably be paying extra for the privilege.
But supposing that you did have a public IP or that you made arrangements to get one, no, you cannot ensure that a port is open via your server program. Your program can listen on that address without much fuss, but you have to consider also firewalls -- probably one on your local machine and one at your local router, at least.
Also, before you set up a public server, you would be wise to check your ISP's policy and user agreement. It is not uncommon for ISPs to forbid running outward-facing services on consumer internet connections. They typically want you to pay more for that privilege, and that also makes it easier for ISPs to police their networks.
I am working on linux Ubuntu 14.04 and trying to multicast using IPv6. I have a link local address of fe80::9a90:96ff:fe98:a985. Running the following code :
int main (int argc, char *argv[]) {
int sd;
struct in6_addr localInterface;
/* Create a datagram socket on which to send/receive. */
sd = socket(AF_INET6, SOCK_DGRAM, 0);
if(sd < 0) {
perror("Opening datagram socket error");
exit(1);
}
else {
printf("Opening the datagram socket...OK.\n");
}
/* Set local interface for outbound multicast datagrams. */
/* The IP address specified must be associated with a local, */
/* multicast capable interface. */
inet_pton (AF_INET6, "fe80::9a90:96ff:fe98:a985", &(localInterface.s6_addr));
if(setsockopt(sd, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&localInterface, sizeof(localInterface)) < 0)
{
perror("Setting local interface error");
printf ("%d\n", errno);
exit(1);
}
else {
printf("Setting the local interface...OK\n");
}
}
gives the error : Setting local interface error : No such device
I have tested multicast to work with IPv4 and also successfully tested that IPv6 works by pinging a local node using ping6 command.
With a few adjustments I was able to modify your program to get it to send multicast packets (that show up in WireShark) on my Mac (running OS/X 10.10.5). I haven't tried it under other OS's, but it should more or less work on other OS's as well.
Note that the program has hard-coded the interface number to 4, since that is what en0 is on my computer; the interface number will likely be different on your computer, and for a generally useful program you'd want to discover the correct interface number dynamically (using getifaddrs() or GetAdaptersAddresses() or similar); it's only hard-coded here for simplicity.
Modified program follows:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
int main (int argc, char *argv[])
{
int sd = socket(AF_INET6, SOCK_DGRAM, 0);
if(sd < 0)
{
perror("Opening datagram socket error");
exit(1);
}
else printf("Opening the datagram socket...OK.\n");
// 4 is the interface ID (scope_id) of interface en0 on my Mac,
// as printed by ifconfig; the appropriate interface index
// value on your computer will likely be different --jaf
int my_network_devices_scope_id = 4;
if(setsockopt(sd, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&my_network_devices_scope_id, sizeof(my_network_devices_scope_id)) < 0)
{
perror("Setting local interface error");
printf ("%d\n", errno);
exit(1);
}
else printf("Setting the local interface...OK\n");
struct sockaddr_in6 multicastIP;
multicastIP.sin6_family = AF_INET6;
multicastIP.sin6_scope_id = my_network_devices_scope_id;
multicastIP.sin6_port = htons(9999); // destination port chosen at random
inet_pton(AF_INET6, "ff12::bead:cede:deed:feed", &multicastIP.sin6_addr.s6_addr); // a multicast address I chose at random
while(1)
{
char buf[] = "hello";
if (sendto(sd, buf, sizeof(buf), 0, (const struct sockaddr *) &multicastIP, sizeof(multicastIP)) == sizeof(buf))
{
printf("Sent a %i-byte multicast packet!\n", (int) sizeof(buf));
}
else perror("sendto");
sleep(1);
}
return 0;
}
My situation is as follows:
I have a windows machine running a UDP Multicast server that is broadcasting packets. I wrote a window client that is able to capture these packets without a problem on a separate windows machine that is connected to the network. I ran into a few firewall problems on the windows machines, but worked that out.
Now, I have an ubuntu 12.04 version of the client; however, my program isn't finding these packets. I ran through all the suggestions provided by other stack overflow posts and some google threads:
when I am running my client, netstat -g shows the IP address of the multicast network
I set the rp_filter to 0 using sysctl
I can see the packets when using tcpdump -i wlan0
Added a route (sudo route add -net 224.0.0.0 netmask 224.0.0.0 wlan0)
For step four, this is a wireless connection established over wlan0, so I add the route on wlan0. Similarly, wlan0's rp_filter=0.
Now, for the code. From the print statements and error checking. I am seeing that I am successfully binding, joining the multicast group, creating the buffer, etc... Then it just blocks at the recvfrom() function call.
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <unistd.h>
#include <pthread.h>
#include <fstream>
#pragma warning( disable : 4996 )
#define MAX_PACKETSIZE 100000 // max size of packet (actual packet size is dynamic)
bool IPAddress_StringToAddr(char *szNameOrAddress, struct in_addr *Address);
void Unpack(char* pData);
#define MULTICAST_ADDRESS "239.255.42.99" // IANA, local network
#define PORT_COMMAND 1510
#define PORT_DATA 1511
#define SOCKET_ERROR -1
#define INVALID_SOCKET -1
typedef int SOCKET;
SOCKET DataSocket;
int main(int argc, char* argv[])
{
int retval;
char szMyIPAddress[128] = "";
in_addr MyAddress, MultiCastAddress;
int optval = 0x100000;
int optval_size = 4;
// client address
if(argc>1)
{
strcpy(szMyIPAddress, argv[1]); // specified on command line
IPAddress_StringToAddr(szMyIPAddress, &MyAddress);
}
else
{ printf("usage: ./client [local_ip_address]\n"); return 0; }
MultiCastAddress.s_addr = inet_addr(MULTICAST_ADDRESS);
printf("Client: %s\n", szMyIPAddress);
printf("Multicast Group: %s\n", MULTICAST_ADDRESS);
// create a "Data" socket
printf("Create Socket.\n");
DataSocket = socket(AF_INET, SOCK_DGRAM, 0);
// allow multiple clients on same machine to use address/port
int value = 1;
printf("Set SO_REUSEADDR sockopt.\n");
retval = setsockopt(DataSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&value, sizeof(value));
if (retval == SOCKET_ERROR)
{
close(DataSocket);
return -1;
}
//bind
struct sockaddr_in MySocketAddr;
memset(&MySocketAddr, 0, sizeof(MySocketAddr));
MySocketAddr.sin_family = AF_INET;
MySocketAddr.sin_port = htons(PORT_DATA);
MySocketAddr.sin_addr = MyAddress;
printf("Bind Socket.\n");
if (bind(DataSocket, (struct sockaddr *)&MySocketAddr, sizeof(struct sockaddr)) == SOCKET_ERROR)
{
printf("[PacketClient] bind failed.\n");
return 0;
}
// join multicast group
struct ip_mreq Mreq;
Mreq.imr_multiaddr = MultiCastAddress;
Mreq.imr_interface = MyAddress;
printf("Join multicast group.\n");
retval = setsockopt(DataSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&Mreq, sizeof(Mreq));
if (retval == SOCKET_ERROR)
{
printf("[PacketClient] join failed.\n");
return -1;
}
// create a 1MB buffer
printf("Create 1MB Buffer.\n");
setsockopt(DataSocket, SOL_SOCKET, SO_RCVBUF, (char *)&optval, 4);
getsockopt(DataSocket, SOL_SOCKET, SO_RCVBUF, (char *)&optval, (socklen_t*)&optval_size);
if (optval != 0x100000)
{
printf("[PacketClient] ReceiveBuffer size = %d\n", optval);
}
//listening
printf("Listening...\n");
char szData[20000];
int addr_len = sizeof(struct sockaddr);
sockaddr_in TheirAddress;
while (1)
{
// Block until we receive a datagram from the network (from anyone including ourselves)
int nDataBytesReceived = recvfrom(DataSocket, szData, sizeof(szData), 0, (sockaddr *)&TheirAddress, (socklen_t*)&addr_len);
Unpack(szData);
}
return 0;
}
// convert ipp address string to addr
bool IPAddress_StringToAddr(char *szNameOrAddress, struct in_addr *Address)
{
int retVal;
struct sockaddr_in saGNI;
char hostName[256];
char servInfo[256];
u_short port;
port = 0;
// Set up sockaddr_in structure which is passed to the getnameinfo function
saGNI.sin_family = AF_INET;
saGNI.sin_addr.s_addr = inet_addr(szNameOrAddress);
saGNI.sin_port = htons(port);
// getnameinfo
if ((retVal = getnameinfo((sockaddr *)&saGNI, sizeof(sockaddr), hostName, 256, servInfo, 256, NI_NUMERICSERV)) != 0)
{
printf("[PacketClient] GetHostByAddr failed.\n");
return false;
}
Address->s_addr = saGNI.sin_addr.s_addr;
return true;
}
void Unpack(char* pData)
{
printf("Begin Packet\n-------\n");
}
Any suggestions are appreciated. Here is the question I used as a reference when trying to fix this problem: UDP socket (multicast) not receiving data (Ubuntu)
I paste my answer here instead writing it in comments.
As I understood you have windows machines on both sides, successfully broadcasting udp packets and now you want to replace them with ubuntu machines. And the machines are receiving the packets, but your client isn't notified.
Maybe this will help
SOL_SOCKET is for the socket layer, IPPROTO_IP for the IP layer, etc... For multicast programming, level will always be IPPROTO_IP
Here is the working code for simplified RIPv2 protocol that sends and reives multicast traffic without an problem.
int setup_sender_connection(struct in_addr interface_addr){
//create socket
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock<0){
die("Creating Socket");
}
//set outgoing interface
if(setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &interface_addr, sizeof(interface_addr))<0){
die("Setting outgoing interface");
}
//disable loopback
u_char loop = 0;
if(setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop))<0){
die("Disabling loopback");
}
//allow reusing of port
int reuse = 1;
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0){
die("Allowing reuse");
}
//bind to this port
struct sockaddr_in saddr;
bzero(&saddr, sizeof(struct sockaddr_in));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(520);
saddr.sin_addr = interface_addr;
if(bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in))<0){
die("Binding");
}
return sock;
}
void join_group(int sock, struct in_addr interface_addr){
//join gorup
struct ip_mreq mreq;
bzero(&mreq, sizeof(struct ip_mreq));
mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_IP); /* IP multicast address of group */
mreq.imr_interface = interface_addr; /* local IP address of interface */
if(setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))<0){
die("Joining group");
}
}
void die(char *error){
perror(error);
exit(1);
}
I'm trying to create TCP Server that should run on a machine with multiple NIC's (eth0, eth1). Each NIC has its own IP from the network and I basically want to be able to connect to the servers running on each of the IP's at the same time. However currently I am able only to connect (netcat) to the first interface IP eth0 and when I try with eth1 I get a "Connection refused" even when I have the server only running on eth1.
I'm not sure if it is a problem with my server code (below). I bind to the required interface with setsockopt() and also use the interface IP (retrieved via ioctl), and netstat shows that the server is listening on the correct ip:port, however I am not able to connect to the one on eth1.
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 255
struct in_addr getIfIp(char* ifName)
{
int sockfd;
struct ifreq ifr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, ifName, IFNAMSIZ-1);
if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0) {
fprintf(stderr, "ioctl failed\n");
}
close(sockfd);
return ((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr;
}
int startServer(char* ifName, unsigned short port)
{
int sock_descriptor, conn_desc;
struct sockaddr_in serv_addr, client_addr;
socklen_t size = sizeof(client_addr);
char buff[MAX_SIZE];
if (ifName == NULL || port == 0) {
fprintf(stderr, "invalid server parameters\n");
return -1;
}
sock_descriptor = socket(AF_INET, SOCK_STREAM, 0);
if(sock_descriptor < 0) {
fprintf(stderr, "Failed creating socket\n");
return sock_descriptor;
}
if (setsockopt(sock_descriptor, SOL_SOCKET, SO_BINDTODEVICE, ifName, strlen(ifName)) < 0) {
fprintf(stderr, "Failed setting socket option\n");
return -1;
}
bzero((char *)&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET; // AddressFamily = Internet address
serv_addr.sin_addr = getIfIp(ifName);//INADDR_ANY;
serv_addr.sin_port = htons(port);
// bind the address to the socket file descriptor
if (bind(sock_descriptor, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
fprintf(stderr, "Failed to bind\n");
return -1;
} else {
printf("bound to %s\n", inet_ntoa(serv_addr.sin_addr));
}
// Now start listening
if (listen(sock_descriptor, 0) < 0){
fprintf(stderr, "Listen failed");
return -1;
} else {// max queue of pending connections
printf("Listening on port %hu ...\n", port);
}
conn_desc = accept(sock_descriptor, (struct sockaddr *)&client_addr, &size);
if (conn_desc == -1) {
fprintf(stderr, "Failed accepting connection\n");
} else {
fprintf(stderr, "Connected\n");
}
close(conn_desc);
close(sock_descriptor);
return 0;
}
Any help with this would be appreciated.
[EDIT]
As mentioned in my comment, one funny thing I noticed is that once I connect to either of the interfaces I can only connect to this interface again and connect attempts to the other fail (for both eth0 and eth1) until a reboot.
Also I guess I would go ahead with INADDR_ANY for now but would really like to hear if anyone could shed some light as to why I can't connect to separate listeners (with my code here) in this case?
To have the socket listen on any interface use INADDR_ANY as listener address ...
serv_addr.sin_addr = INADDR_ANY;
and remove the call to setsockopt().
I'm not sure whether a back-log size of 0 makes sense. Also the code misses to test the outcome of the call to listen().
Finally int size should be socklen_t size.