Nom de domaine qui renvoi vers localhost

a marqué ce sujet comme résolu.

Bonjour, j’ai une question sur un site web que j’administre. Depuis aujourd’hui (me semble-t-il) le nom de domaine renvoi vers localhost. Si je tape "https://mon-nom-de-domaine.fr/ma-page/", le navigateur est redirigé vers "https://localhost/ma-page/". Le problème se produit aussi lorsque je me connecte depuis mon portable en 4G, donc ça ne vient pas de mon ordi ou mon routeur. Ça fonctionnait la dernière fois que je me suis connecté, et je n’ai fait aucune intervention entre temps.

Sur le site de mon hébergeur, je n’ai rien trouvé non plus. Le nom de domaine n’a pas expiré. Je n’ai reçu aucun email de sa part.

Je peux me connecter au serveur en SSH sans problème. NGinx, tourne, Supervisor aussi. Je ne comprends pas d’où vient le problème.

Comment je peux diagnostiquer cela ?

Merci d’avance.

EDIT : dans les logs, j’ai

2023/12/01 01:02:40 [crit] 480200#480200: *7219 SSL_do_handshake() failed (SSL: error:141CF06C:SSL routines:tls_parse_ctos_key_share:bad key share) while SSL handshaking, client: 45.55.0.38, server: 0.0.0.0:4>
2023/12/01 02:53:18 [crit] 480200#480200: *7245 SSL_do_handshake() failed (SSL: error:141CF06C:SSL routines:tls_parse_ctos_key_share:bad key share) while SSL handshaking, client: 118.123.105.93, server: 0.0.
2023/12/01 19:14:12 [crit] 556528#556528: *1 connect() to unix:/tmp/gunicorn.[dns].sock failed (2: No such file or directory) while connecting to upstream, client: [ip], server: [dns], request: "GET / HTTP/1.1", upstream: "http://unix:/tmp/gunicorn.[dns].sock:/", host: "[dns]"

Donc ça viendrait d’un problème avec le certificat ? Ça se corrige comment ça ?

+1 -0

Curieux comme problème.

Si ton navigateur redirige vers localhost, c’est qu’il a certainement reçu un statut 30X.

Tu peux vérifier avec: curl -sSD - https://ton-site.fr -o /dev/null et nous retourner les headers ?

En tout cas, le seul truc que je rapproche à localhost, c’est cette IP: 45.55.0.38 dont le DNS inverse pointe vers apzg-0720c-041.stretchoid.com. qui lui même pointe vers 127.0.0.1. La deuxième IP ne nous aide pas trop.

Je ne comprends pas bien cette histoire de certificat. Tu as quoi si tu fais: echo | openssl s_client -connect ton-site.fr:443. Si tu as un DONE en dernière ligne, c’est que tout est bon.

+1 -0

Ça donne un « moved permanently » :

HTTP/1.1 301 Moved Permanently
Server: nginx/1.18.0
Date: Fri, 01 Dec 2023 23:41:17 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Location: https://localhost/
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin

Et j’ai bien le DONE pour la deuxième commande.

+1 -0

Ok, donc tout est bon coté SSL. Et tu reçois bien une 301, comme prévu. 👍

Donc, c’est soit ton serveur (nginx) qui est mal configuré, soit ton application qui fait n’importe-quoi.

Pour comprendre ce qu’il se passe, il va falloir regardé ta configuration nginx. Tu peux cacher si tu veux le nom de domaine de ton site.

Si on trouve rien, il va falloir regarder l’application, en particulier son code source et sa configuration. 🤷
Mais en tout cas, le problème vient d’un des deux. Car là, ce n’est pas un bug, c’est une fonctionnalité qui fonctionne. ^^

+5 -0

voici la config :

upstream [dns] {
  server     unix:/tmp/gunicorn.[dns].sock fail_timeout=30s;
}

server {
#  listen                443 ssl;
#  listen                [::]:443 default_server ssl;

  server_name          [dns].fr;

  access_log            /var/log/nginx/[dns].log;
  error_log             /var/log/nginx/[dns].error.log;

  location /static/ {
    alias  /home/[user_name]/django/[dns]/static/;
  }

  location /favicon.ico {
    alias /home/[user_name]/django/[dns]/static/blog/favicon16×16.webp;
  }

  location /medias/uploads/ {
    alias /home/[user_name]/django/[dns]/medias/uploads/;
    expires 1w;
    try_files $uri @django;
}

  location / {
           proxy_pass http://unix:/tmp/gunicorn.[dns].sock; # Pass to Gunicorn
           proxy_set_header X-Real-IP $remote_addr; # get real Client IP
      }

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/[dns].fr/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/[dns].fr/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot



}


server {
    if ($host = [dns].fr) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


  listen                80;
  listen                [::]:80;

  server_name          [dns].fr;
    return 404; # managed by Certbot


}

Il y a bien la redirection du port 80 vers le port 443. Mais ça marchait avant donc je vois pas trop. La modification la plus récente que j’ai faite dans ce fichier c’est le location /favicon.ico, mais pareil, ça remonte un peu et ça fonctionnait encore il y a quelques jours. Donc je ne comprends pas pourquoi c’est arrivé comme ça.

là, ce n’est pas un bug, c’est une fonctionnalité qui fonctionne. ^^

Flûte, faut pas que Microsoft tombe sur ce topic, ça pourrait leur donner des idées…

+1 -0

La config Nginx a l’air OK …du coup est-ce que ce ne serait pas le routage dans ton appli ? si on en croit les lignes 1 et 7 de ta sortie curl… :/ Regarde aussi ton fichier hosts et ta configuration DNS

+1 -0

On parle du fichier urls.py ?

from django.contrib import admin
from django.urls import path, include
from django.shortcuts import redirect
from django.conf import settings
from django.conf.urls.static import static
from django.views.generic import base

handler404 = 'blog.views.error_404'

urlpatterns = [
    path('', lambda request: redirect('articles/')),
    path('', include('blog.urls')),
    path('admin/', admin.site.urls),
    path('markdownx/', include('markdownx.urls')),
    path("favicon.ico", base.RedirectView.as_view(url='static/blog/favicon16×16>

]


if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL,
                          document_root=settings.MEDIA_ROOT)

pour le fichier hosts:

127.0.0.1       localhost
127.0.1.1       debian.localdomain      debian
127.0.0.1       blog

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

OK, rien d’alarmant non plus dans le /etc/host ni dans le urls.py de prime abord. Est-ce que le /etc/resolv.conf a été modifié récemment ? Et comme le fait remarquer ache, est-que 45.55.0.38 correspond bien à ton serveur ? (il se peut que le fin mot de l’histoire et que l’hébergeur ait merdé au niveau du DNS)

+0 -0

Et comme le fait remarquer ache, est-que 45.55.0.38 correspond bien à ton serveur ?

Non, c’est une fausse piste. C’est l’IP d’un bot aux USA.

J’ai fais une réponse un peu complète …
Y a un récap' à la fin du poste, si tu veux.

Il y a bien la redirection du port 80 vers le port 443.

Franchement, c’est le premier truc suspect mais quand je le regarde, je vois rien. J’ai pour habitude de mettre le server_name au début mais ça ne change rien du tout. Si on veut vraiment innocenter ce bloc, il faudrait le changer temporairement de 301 vers 302. Redémarrer nginx, refaire curl pour vérifier que c’est bien encore un 301. Mais à mon avis, ça sera encore un 301, ce n’est pas ça.

Un autre truc un peu suspect, c’est la mise en place du proxy avec ton proxy_pass.
Il te faut peut-être un redirect_off.

  location / {
           proxy_redirect off; # Be dumb nginx and do what I want
           proxy_pass http://unix:/tmp/gunicorn.[dns].sock; # Pass to Gunicorn
           proxy_set_header X-Real-IP $remote_addr; # get real Client IP
      }

Avec un peu de chance, c’est juste nginx qui essaye d’être malin. 🤞

Aussi ! Le dossier /tmp, s’il est monté par systemd peut-être géré différemment des autres et avoir PrivateTmp ce qui pourrait le rendre invisible (mais dans ce cas là, tu aurais eu un 404, pas un 301). Dans tous les cas, je te conseil de mettre ton socket linux dans /var/run ou /srv/

Si ce n’est pas le proxy, du coup, ben je vois que l’application. Pour innocenter (ou inculper ! 😈) l’application, il faudrait créer une application basique qui retourne constamment disons au pif un code de statut 418.


J’ai mis en place rapidement ce petit serveur:

upstream teapot {
  server unix:/srv/tea.sock fail_timeout=0;
}

server {
  listen                80;
  listen                [::]:80;

  server_name          tea.local;

  access_log            /var/log/nginx/tea.log;
  error_log             /var/log/nginx/tea.error.log;

  location / {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_pass http://unix:/srv/tea.sock;
  }
}

Mais garde ta configuration. Tu n’as pas besoin de la changer.

Avec: 127.0.0.1 tea.local dans le fichier host.

Et comme application:

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>I'm a teapot ! 🫖</p>", 418

Dans un fichier tea.py, qu’on pourra alors appeler avec gunicorn avec tea:app.

Et en lançant gunicorn avec: sudo gunicorn --bind unix:/srv/tea.sock tea:app.

Mais du coup, tu peux juste faire sudo gunicorn --bind unix:/tmp/gunicorn.[dns].sock tea:app chez toi comme ça tu ne modifies pas ta configuration nginx. Attention à bien éteindre django avant.

Et curl:

$ curl -sSD - http://tea.local
HTTP/1.1 418 I'M A TEAPOT
Server: nginx/1.24.0
Date: Sat, 02 Dec 2023 18:04:50 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 26
Connection: keep-alive

<p>I'm a teapot ! 🫖</p>

Ça marche bien.


Bref à tester:

  • Changer le 301 en 302, redémarrer nginx et vérifier que c’est encore 301. C’est rapide.
  • Rajouter proxy_redirect off; puir redémarrer nginx.
  • Changer le chemin du socket pour qu’il ne soit pas dans /tmp, c’est rapide mais par-contre, c’est peu probable que ça soit ça.
  • On peut essayer d’inculper l’application en la remplaçant par une application Flask (Django mais genre vraiment light).

Après, si même après ces trois étapes, tu as une 301. Il va falloir vérifier que tu tapes sur le bon nginx. :p
Ça nous est tous arrivé au moins une fois.

+2 -0

Changer le 301 en 302, redémarrer nginx et vérifier que c’est encore 301. C’est rapide.

Ok, je viens de tester. Si je fais curl -sSD - https://[dns].fr/ -o /dev/null j’obtiens

HTTP/1.1 301 Moved Permanently
Server: nginx/1.18.0
Date: Sun, 03 Dec 2023 09:34:17 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Location: https://localhost/
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin

Mais si je fais curl -sSD - [dns].fr/ -o /dev/null. J’obtiens

HTTP/1.1 302 Moved Temporarily
Server: nginx/1.18.0
Date: Sun, 03 Dec 2023 09:34:35 GMT
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Location: https://[dns].fr/

À priori ça indique que le problème ne viens pas de là non ?

Rajouter proxy_redirect off; puir redémarrer nginx.

Non, ça change rien.

Aussi ! Le dossier /tmp, s’il est monté par systemd peut-être géré différemment des autres et avoir PrivateTmp ce qui pourrait le rendre invisible (mais dans ce cas là, tu aurais eu un 404, pas un 301). Dans tous les cas, je te conseil de mettre ton socket linux dans /var/run ou /srv/

Va falloir mettre à jour ce tutoriel dans ce cas.

J’ai pas encore testé.

On peut essayer d’inculper l’application en la remplaçant par une application Flask (Django mais genre vraiment light).

idem, je vous redis dès que j’aurai testé. Je suis pas certain d’avoir le temps ce week-end.

Juste pour valider la méthodologie :

  1. je crée un fichier site-available/teapot.conf/ avec ta config et un lien symbolique dans site-enabled
  2. Je modifie le fichier host (pourquoi ?)
  3. Je crée un virtual env dans mon répertoir utilisateur, pip install flask, et je crée le fichier python avec ton code.
  4. je lance gunicorn puis curl.

C’est bien ça ?

EDIT : au passage, l’adresse https://[dns].fr/favicon.ico fonctionne correctement. Si jamais ça peut aider au diagnostique.

+0 -0

À priori ça indique que le problème ne viens pas de là non ?

Yep, ça, ça marche et ce n’est pas le problème.
Dans un sens tant mieux. 🤷

Rajouter proxy_redirect off; puir redémarrer nginx.

Non, ça change rien.

Dommage, très franchement, j’aurais espéré que ça soit ça.

Va falloir mettre à jour ce tutoriel dans ce cas.

👍 Très bonne idée.

Juste pour valider la méthodologie :

  1. je crée un fichier site-available/teapot.conf/ avec ta config et un lien symbolique dans site-enabled
  2. Je modifie le fichier host (pourquoi ?)
  3. Je crée un virtual env dans mon répertoir utilisateur, pip install flask, et je crée le fichier python avec ton code.
  4. je lance gunicorn puis curl.

C’est bien ça ?

Zut ! Non, juste les deux dernières étapes pour toi.

Donc créer:

  1. Créer un environnement virtuel. C’est détaillé sur le guide d’installation, au besoin en gros:
    1. Création de l’environnement virtuel.
    2. Installer pip install Flask, oui, y a une majuscule (🤷).
    3. Créer le fichier tea.py avec le contenu que j’ai posté.
  2. S’assurer que le gunicorn de Docker est éteins. Je ne sais pas comment tu lances ce gunicorn. Si tu suis le tutoriel alors tu utilises supervisord donc la commande est supervisorctl stop NOM_DU_PROGRAMME.
  3. Lancer le gunicorn de l’application tea.py à la main, dans son environnent virtuel. Pas besoin d’utiliser supervisord ici. sudo gunicorn --bind unix:/tmp/gunicorn.[dns].sock tea:app (le sudo, je pense n’est pas obligatoire mais dans le doute). Ici, je cherche à remplacer le socket de ta configuration Django, comme ça tu n’as pas besoin de modifier ta configuration nginx.
    Pense bien à remplacer [dns] par le tiens, enfin tu sais. ;)
  4. curl, tu devrais obtenir une 418. Si tu as une 418, c’est que le problème vient du programme. Sinon, c’est ailleurs.

À la fin du test, tu peux supprimer l’environnement virtuel.


EDIT : au passage, l’adresse https://[dns].fr/favicon.ico fonctionne correctement. Si jamais ça peut aider au diagnostique.

Tu as une adresse défini juste pour ça:

  location /favicon.ico {
    alias /home/[user_name]/django/[dns]/static/blog/favicon16×16.webp;
  }

Donc, je dirais que c’est un indice que nginx marche bien comme il faut.

+2 -0

Hello, je viens de tester :

$curl -sSD - [dns].fr/ -o /dev/null

HTTP/1.1 301 Moved Permanently
Server: nginx/1.18.0
Date: Mon, 04 Dec 2023 20:20:24 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://[dns].fr/

$curl -sSD - https://[DNS].fr/ -o /dev/null

HTTP/1.1 418 I'M A TEAPOT
Server: nginx/1.18.0
Date: Mon, 04 Dec 2023 20:20:13 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 26
Connection: keep-alive

Donc c’est que ça viens bien de l’app si je comprends bien.

EDIT : j’ai checké un peu mon git. Les seuls modifications notables que j’ai faites récemment semblent être l’ajout de

SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

à mon setting.py pour tenter de résoudre un problème que j’avais à l’époque : les flux rss n’utilisaient pas https dans les liens. Problème non résolut à ce jour, mais secondaire dans l’immédiat.

EDIT 2 : cherchez plus, c’était ça. J’ai commenté le SECURE_SSL_REDIRECT = True et j’ai pu me connecter direct. D’après la doc, il semblerait qu’il faille configurer je ne sais trop comment la variable SECURE_PROXY_SSL_HEADER. Si quelqu’un en sais un peu plus sur le fonctionnement de ces fonctionnalité, je suis preneur.

Merci pour votre aide en tout cas ! J’aurais pu chercher longtemps sans vous.

+1 -0

En gros, si j’ai les neurones encore en éveil, ton site est https (Nginx fait la redirection des http tout court vers https, et pour ton appli fait le mandataire/intermédiaire) ; mais une option de ton appli en local lui dit qu’il faut que rediriger le http tout court (ici en local et qui arrive par une chaussette) en https …d’où l’erreur (on fini en https://localhost/… arf.)

+1 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte