connect() - IP blocked, how to connect using hostname? - sockets

when I try to connect to a webserver, my "FritzBox" (residential gateway device) is configured to block all connections that connect directly to an IP, not a host name.
However, the connect() function only lets me connect using an IP address.
How can I connect() to a server using the host name (the way web browsers do)?
Many thanks.

... my "FritzBox" (residential gateway device) is configured to block all connections that connect directly to an IP, not a host name...
It looks like you are trying to bypass the settings of the child protection feature of the Fritzbox. What these settings mean in reality is that it will only allow HTTP connections which have a real hostname inside the Host-header of the HTTP-Request and not connections containing an IP only, i.e. it will allow http://example.com/ but not http://10.10.10.10/. For an example of the Host header look at the HTTP example request at Wikipedia.

First of all connections are always connecting to an IP address, not a host name. So your gateway is doing something else than what you're telling us, it can't tell the difference on how a client connects to something. What it could do is inspect certain protocols specifically, e.g. look for a Host: header in HTTP requests.
But to answer your question: You need to look up the host name with DNS and convert it to an IP address. This can be done all in one go by the getaddrinfo() function, getaddrinfo() will perform lookups in a platform specific way by e.g. looking at host files and/or do DNS lookups: e.g.
int clientfd;
struct addrinfo hints, *servinfo, *p;
int rc;
const char *port = "80";
const char *host = "www.google.com";
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((rc = getaddrinfo(host, port, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
exit(1);
}
// getaddrinfo() can map the name to several IP addresses
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((clientfd= socket(p->ai_family,
p->ai_socktype,p->ai_protocol)) == -1) {
perror("socket()");
continue;
}
if (connect(clientfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
continue;
}
break; //got a connection
}
if (p == NULL) {
fprintf(stderr, "connect() failed\n");
exit(2);
}
freeaddrinfo(servinfo);
//use clientfd

Related

Query regarding SSL_connect and HTTPS

I wanted send an HTTPS request through a proxy server and obtain the HTML of the landing page of the site. The socket creation went smoothly but when i wanted to make an SSL connection to the server it gave me a "Aborted (Core Dumped)" error. I've narrowed the cause down to the SSL_connect function. When i tried to do the same without the proxy server (using struct addrinfo instead of struct sockaddr since I needed to make a DNS query to get the IP), it worked perfectly and I was able to get a valid HTTP response along with the HTML. Can someone help me out ?
SSL_library_init();
SSL_load_error_strings();
ssl_ctx = SSL_CTX_new(SSLv23_client_method ());
int sockfd2 = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in httpsProxy;
httpsProxy.sin_family = AF_INET;
httpsProxy.sin_addr.s_addr = inet_addr("<insert IP>");
httpsProxy.sin_port = htons(13128);
connect(sockfd2,(struct sockaddr *)&httpsProxy,sizeof(httpsProxy));
SSL *conn = SSL_new(ssl_ctx);
SSL_set_fd(conn, sockfd2);
int err = SSL_connect(conn);
You need to connect to the proxy and request it to connect to the target HTTPS server, without using SSL/TLS yet while communicating with the proxy, and only if successful THEN perform the SSL/TLS handshake via SSL_connect() once you are communicating with the HTTPS server, not with the proxy anymore.
SSL_library_init();
SSL_load_error_strings();
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in httpsProxy = {};
httpsProxy.sin_family = AF_INET;
httpsProxy.sin_addr.s_addr = inet_addr("<proxy IP>");
httpsProxy.sin_port = htons(13128);
// connect to proxy...
if (connect(sockfd, (struct sockaddr *)&httpsProxy, sizeof(httpsProxy)) < 0)
{
...
close(sockfd);
return;
}
// ask proxy to connect to target HTTPS server...
if (!<connect proxy to HTTPS server>)
{
...
close(sockfd);
return;
}
// NOW start SSL/TLS with HTTPS server...
ssl_ctx = SSL_CTX_new(SSLv23_client_method ());
SSL *conn = SSL_new(ssl_ctx);
SSL_set_fd(conn, sockfd);
int err = SSL_connect(conn);
...

getsockname() shows 127.0.0.1 after connect() to public IP

I'm struggling to make sense of this. The issue is seen on a machine that is:
Remote (I do not have access to it)
Running Windows 7
NOT running a proxy or VPN (or so I have been told)
My application has a snippet of code that tries to quickly determine which interface the OS prefers. It does the following:
// Create a socket
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
// Resolve DNS query
DWORD dwRemoteIp = GetHostAddr("www.google.com")
// I've simplified the call here, but "www.google.com" resolves to 172.217.3.100 in host byte order, so the resolution is correct
// Create the remote address to connect to
sockaddr_in remoteaddr = {0};
remoteaddr.sin_family = AF_INET;
remoteaddr.sin_addr.s_addr = htonl(dwRemoteIp);
remoteaddr.sin_port = htons(80);
// Connect the socket
if (0 == connect(sock, (struct sockaddr*)&remoteaddr, sizeof(remoteaddr))) {
// The connection succeeded -- see which local address was bound to
sockaddr_in localaddr = {0};
int len = sizeof(localaddr);
if (0 == getsockname(sock, (struct sockaddr*)&localaddr, (socklen_t *)&len)) {
// Here is where I see dwLocalIp == 0x7F000001, or 127.0.0.1
DWORD dwLocalIp = ntohl(localaddr.sin_addr.s_addr);
}
}
What could be going on here?

Create & send DHCP packets with source address 0.0.0.0 in Mac OS

I’m trying to create and send DHCP REQUEST message over a raw socket on Mac OS X. I’m able to create and send a well formatted message with the exception of the Source IP address. It should be 0.0.0.0.
Wireshark indicates the source address is whatever I set in the ip_src.s_addr field of the IP header, unless I use 0.0.0.0. When I use 0.0.0.0 Wireshark shows the IP as the machine sending the packet. FWIW, I can set destination IP to 255.255.255.255 no problem.
How do I set the source IP to 0.0.0.0?
Also what is the purpose of sin_addr.s_addr field used in sin parameter passed to the sendto function? Changing it or leaving it unset seems to have no effect.
Code:
int s = socket (PF_INET, SOCK_RAW, IPPROTO_RAW);
if (s < 0)
{
perror("Failed to create raw socket");
exit(1);
}
if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0)
{
perror("Failed to set raw socket options");
exit(1);
}
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_BROADCAST;
sin.sin_port = htons(67);
inet_pton(AF_INET, "255.255.255.255", &sin.sin_addr);
if (sendto (s, DHCPPacket, DHCPPacketLength, 0, (struct sockaddr *) &sin, sizeof (struct sockaddr)) < 0)
{
perror("sendto failed");
exit(-1);
}
else
{
printf ("Packet Send. Length : %d Payload size: %d Options size: %d\n", DHCPPacketLength, sizeof(DHCPmsgType),sizeof(DHCP_VendorType));
}

Is it possible to use the same port and ip address?

I created a TCP server program which binds, listen and accepting a connection from the specific ip address and port number.
During the first connection : Server is accepting a SYN packet from the client and sending an ACK back to the client. Later getting a ACK from the client. Finally Client is RST with the server.
During the second connection the client is sending a SYN packet to the slave but there is no ACK from the server.
I think there is no binding is possible during the second connection with the same ip address and port number.
Is it possible to bind with the SAME ip address and port number in the second connection ?
server :
SOCKET sock;
SOCKET fd;
uint16 port = 52428;
// I am also using non blocking mode
void CreateSocket()
{
struct sockaddr_in server, client; // creating a socket address structure: structure contains ip address and port number
WORD wVersionRequested;
WSADATA wsaData;
int len;
int iResult;
u_long iMode = 1;
printf("Initializing Winsock\n");
wVersionRequested = MAKEWORD (1, 1);
iResult = WSAStartup (wVersionRequested, &wsaData);
if (iResult != NO_ERROR)
printf("Error at WSAStartup()\n");
// create socket
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
printf("Could not Create Socket\n");
//return 0;
}
printf("Socket Created\n");
iResult = ioctlsocket(sock, FIONBIO, &iMode);
if (iResult < 0)
printf("\n ioctl failed \n");
// create socket address of the server
memset( &server, 0, sizeof(server));
// IPv4 - connection
server.sin_family = AF_INET;
// accept connections from any ip adress
server.sin_addr.s_addr = htonl(INADDR_ANY);
// set port
server.sin_port = htons(52428);
//Binding between the socket and ip address
if(bind (sock, (struct sockaddr *)&server, sizeof(server)) < 0)
{
printf("Bind failed with error code: %d", WSAGetLastError());
}
//Listen to incoming connections
if(listen(sock, 10) == -1){
printf("Listen failed with error code: %d", WSAGetLastError());
}
printf("Server has been successfully set up - Waiting for incoming connections");
for(;;){
len = sizeof(client);
fd = accept(sock, (struct sockaddr*) &client, &len);
if (fd < 0){
printf("Accept failed");
closesocket(sock);
}
//echo(fd);
printf("\n Process incoming connection from (%s , %d)", inet_ntoa(client.sin_addr),ntohs(client.sin_port));
//closesocket(fd);
}
}
TCP connections are identified by four parameters:
Local IP
Local port
Remote IP
Remote port
The server normally uses the same Local IP and port for all its connections (e.g. an HTTP server listens on port 80 for all connection). Each connection from a client will have a different Remote IP and/or Remote port, and these resolve the ambiguity.
When the server closes all of its connected sockets, the TCB sticks around for several minutes in a TIME_WAIT state. This normally prevents a process from binding to the port, because you can't bind to a local IP/port that has any associated TCBs. If you want to restart the server and bind to the same port and address that it just used for connections, you need to use the SO_REUSEADDR socket option to get around this. See:
Socket options SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do they mean the same across all major operating systems?
for details of this.

How to force client in UDP to open port when sending with sendto

I have simple server and client in UDP (WinSocks/C++).
I send datagram client -> server via sendto, and reply from server to client using the ip and port obtained from recvfrom function.
I found out that:
Every sendto from client is being sent from different port
When trying to reply from server Windows returns WSAECONNRESET (which mean that port is closed - http://support.microsoft.com/kb/263823)
How can I properly answer client from server (ie force port binding on client when sending using sendto?)
Edit: Adding some source code:
bool InitClient()
{
internal->sock = socket(PF_INET, SOCK_DGRAM, 0);
char8 yes = 1;
setsockopt(internal->sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int32));
return internal->sock != -1;
}
void Send(const IpAddress & target, const uint16 port, const char8 * data, int32 size )
{
sockaddr_in trgt;
memset(&trgt, 0, sizeof(trgt));
trgt.sin_family = AF_INET;
trgt.sin_port = htons(port);
trgt.sin_addr.s_addr = target.GetRaw();
if(sendto(internal->sock, (const char8 *)data, size, 0, (PSOCKADDR)&trgt, sizeof(trgt)) == SOCKET_ERROR)
{
LOG("Network sending error: %d", WSAGetLastError());
}
}
Call the "bind" function to specify a local port to send from. Example of using port 4567 below. Make sure to check the return value from bind.Call this code after you create the socket.
sockaddr_in local = {};
local.family = AF_INET;
local.port = htons(4567);
local.addr = INADDR_ANY;
bind(internal->sock,(sockaddr*)&local, sizeof(local));
If you bind to port zero instead of 4567 then the os will pick a random port for you and use it for all subsequent send and receives. You can call getsockname to discover which port the os picked for you after calling bind.