2017-08-23 19 views
0

J'ai écrit un serveur simple en C qui ne semble pas très différent de tous les exemples que vous trouverez sur Internet. La seule chose qu'il fait est d'écouter le port 80 sur une adresse IP spécifique et de rediriger tout accès à un site différent. Le site redirigé par ce logiciel est mon domaine personnel que j'ai utilisé pendant des années avec nginx. Mon serveur est FreeBSD et fonctionne sur un VPS.Peut accéder au serveur par IP mais pas le nom de domaine

Je désactive le serveur pour le site redirigé et démarre mon programme de serveur personnalisé. Si j'entre l'adresse IP dans la barre d'adresse du navigateur, le serveur fonctionne comme prévu et obtient le statut 302 et redirige vers l'autre site. Si j'entre le nom de domaine dans la barre d'adresse, les navigateurs signalent une erreur "Impossible de se connecter" bien que mon logiciel serveur imprime qu'il a reçu une connexion. Lynx dit,

HTTP/1.1 302 temporaire Redirect

mais se bloque juste là.

Fait intéressant, en faisant curl -I http://example.com/ retours ce que j'attendre:

HTTP/1.1 302 temporaire Redirect

Content-Length: 40

Lieu: https://othersite.com

Je ne Je ne comprends pas pourquoi je suis capable de faire ce travail par IP mais sans utiliser le nom de domaine.

#include <stdlib.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <string.h> 
#include <unistd.h> 

#define MAXLINE 4096 /*max text line length*/ 
#define SERV_PORT 80 /*port*/ 
#define LISTENQ 1 /*maximum number of client connections*/ 

int main (int argc, char **argv) 
{ 
int listenfd, connfd, n; 
pid_t childpid; 
socklen_t clilen; 
char buf[MAXLINE]; 
struct sockaddr_in cliaddr, servaddr; 

//Create a socket for the soclet 
//If sockfd<0 there was an error in the creation of the socket 
if ((listenfd = socket (AF_INET, SOCK_STREAM, 0)) <0) { 
    perror("Problem in creating the socket"); 
    exit(2); 
} 


//preparation of the socket address 
servaddr.sin_family = AF_INET; 
servaddr.sin_addr.s_addr = inet_addr("xxx.xxx.xxx.xxx"); 
servaddr.sin_port = htons(SERV_PORT); 

//bind the socket 
bind (listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); 

//listen to the socket by creating a connection queue, then wait for clients 
listen (listenfd, LISTENQ); 

for (; ;) { 

    clilen = sizeof(cliaddr); 
    //accept a connection 
    connfd = accept (listenfd, (struct sockaddr *) &cliaddr, &clilen); 

    if ((childpid = fork()) == 0) {//if it's 0, it's child process 

    //close listening socket 
    close (listenfd); 

    while ((n = recv(connfd, buf, MAXLINE,0)) > 0) { 
    send(connfd, "HTTP/1.1 302 Temporary Redirect\nContent-Length: 40\nLocation: https://example.org\n\n", 93, 0); //NOTE: I'm aware the length is wrong here due to my editing the name out. 
    } 

    exit(0); 
} 
//close socket of the server 
close(connfd); 
} 
} 
+1

Est-ce un problème EOL? Http devrait utiliser CRLF. Il semble que certains clients sont plus tolérants que d'autres. – captncraig

+0

@captncraig Je n'ai eu aucun problème avec CRLF et je pensais lire quelque part que '\ n' est tout ce dont vous avez besoin, mais je l'ai essayé avec' \ r \ n' et cela n'a pas résolu le problème. Notez que cela fonctionne avec une adresse IP. – Rob

+0

Est-ce que l'onglet réseau chrome montre quelque chose d'intéressant? Peut-être une demande de favicon ou quelque chose qui se casse? Je ne suis pas tout à fait le forking, mais il semble que vous fermez l'auditeur après une demande peut-être? – captncraig

Répondre

0

La raison pour laquelle j'ai eu tellement de problèmes pour que cela fonctionne est simple. J'avais oublié que \ n est un caractère de contrôle mais le comptait dans la longueur de deux. En outre, le site était à l'origine l'envoi de HSTS dont les navigateurs se souviendront et tenteront automatiquement d'accéder à la version https pendant que j'essayais de rediriger depuis http. Donc, cela explique pourquoi je pourrais obtenir ceci pour travailler dans le lynx et le curling mais pas d'autres.