| Both sides previous revisionPrevious revisionNext revision | Previous revision |
| proyecto:conexion_externa [2018/05/01 19:42] – ahogan | proyecto:conexion_externa [2026/09/25 18:31] (current) – Lenguaje sin género en la guía del servidor semorale |
|---|
| ====== Conexión Externa ====== | ====== Conexión Externa ====== |
| |
| Si alguien quiere conectar al servidor desde afuera (por ejemplo, para probar una aplicación desde tu notebook), aquí van los detalles. | Por defecto, Postgres solo acepta conexiones que vienen de la misma máquina. Eso basta mientras trabajen con ''psql'' dentro del servidor, pero no sirve si quieren conectarse desde su notebook (con ''psql'', DBeaver o pgAdmin) o desde una aplicación que corre en su computador. Esta página explica cómo abrir esa puerta. Toma unos 15 minutos. |
| |
| ===== Los Puertos ===== | Todo esto supone que ya siguieron [[proyecto:configurar_postgres|Configurar Postgres]]. En los ejemplos usamos la máquina 40. |
| |
| Para empezar, el puerto de Postgres por defecto es 5432, pero dado que tenemos un hostname (cc3201.dcc.uchile.cl) y 20+ bases de datos, claro que no podemos usar sólo el puerto 5432, entonces hay que usar 54XX donde XX es el número del grupo. Por ejemplo, si uno estuviera en grupo 6, el puerto sería 5406; si estuviera en grupo 21, sería 5421. | ===== Cómo llega una conexión a su máquina ===== |
| | |
| | Su máquina virtual no tiene una dirección propia en internet. Todas las máquinas del curso están detrás de ''cc3201.dcc.uchile.cl'', que reenvía cada puerto a la máquina que corresponde: |
| | |
| | {{proyecto:servidor_mapa_puertos.png?direct&900|El puerto 3XX llega al SSH de la máquina XX y el 55XX a su Postgres}} |
| | |
| | Un **puerto** es un número que identifica a qué programa va dirigida una conexión dentro de una máquina. SSH atiende en el puerto 22 y Postgres en el 5432. Desde afuera, el puerto ''3XX'' de ''cc3201.dcc.uchile.cl'' llega al puerto 22 de la máquina ''XX'', y el ''55XX'' llega al 5432. |
| | |
| | Para que una conexión desde afuera llegue a su base de datos, tiene que pasar dos filtros de Postgres, y los dos vienen cerrados: |
| | |
| | {{proyecto:servidor_dos_filtros.png?direct&900|Primero listen_addresses y después pg_hba.conf}} |
| | |
| | Hay que hacer tres cosas en el servidor: darle una contraseña a su rol de Postgres, abrir los dos filtros y reiniciar Postgres. Al final hay una prueba para ver si quedó funcionando. |
| | |
| | ^ Término ^ Qué es ^ |
| | | **localhost** | "Esta misma máquina". Su dirección IPv4 es ''127.0.0.1'' y la IPv6 es ''::1''. | |
| | | **dirección IP** | El número que identifica a un computador en la red. Hay dos formatos, IPv4 (como ''192.80.24.220'') e IPv6 (como ''2001:db8::1''). | |
| | | **0.0.0.0/0** | "Cualquier dirección IPv4". El ''/0'' indica cuántos bits de la dirección tienen que coincidir; con 0, sirve cualquiera. ''::0/0'' es lo mismo en IPv6. | |
| | | **postgresql.conf** | El archivo de configuración general de Postgres. | |
| | | **listen_addresses** | La opción de ''postgresql.conf'' que dice en qué direcciones de red escucha Postgres. | |
| | | **pg_hba.conf** | El archivo que decide quién puede conectarse, a qué base y desde dónde (//hba// viene de //host-based authentication//). | |
| | | **scram-sha-256** | El método de autenticación que pide contraseña y la envía cifrada. | |
| | |
| | ===== Paso 1: la contraseña ===== |
| | |
| | Primero hay que configurar la contraseña de Postgres. No es la misma contraseña que la de SSH para ingresar al servidor. De hecho, en principio su rol no tiene contraseña. Dentro del servidor, Postgres confía en que ustedes son ''cc3201'' porque entraron por SSH con ese usuario de Linux (eso se llama autenticación //peer//). Desde afuera no hay cómo saberlo, así que Postgres va a pedir una contraseña. |
| | |
| | En ''psql'', hay que poner: |
| | |
| | <code>\password cc3201</code> |
| | |
| | Pide la contraseña dos veces y no muestra nada al escribirla: |
| | |
| | {{proyecto:servidor_ext_01_password.png?direct&770|Definir la contraseña de Postgres con \password}} |
| | |
| | Esta es la contraseña que van a usar para conectarse desde su notebook o desde la aplicación. Como el puerto de Postgres va a quedar abierto a todo internet, elijan una contraseña larga y que no sea la misma de SSH. Después salgan de ''psql'' con ''\q'', porque lo que sigue se hace en la terminal del servidor. |
| | |
| | ===== Paso 2: ver la versión y el estado actual ===== |
| | |
| | Los archivos de configuración están en una carpeta que lleva el número de versión de Postgres. Para verla, y de paso ver en qué direcciones escucha Postgres ahora: |
| |
| <code> | <code> |
| hostname: cc3201.dcc.uchile.cl | ls /etc/postgresql/ |
| puerto: 54XX (donde XX es el número del grupo) | ss -ltn | grep 5432 |
| </code> | </code> |
| |
| ===== Una Prueba ===== | {{proyecto:servidor_ext_02_version_y_puertos.png?direct&900|La carpeta es 17 y Postgres escucha solo en 127.0.0.1}} |
| |
| Para ver si funciona o no, hay un proyecto de Java aquí ([[http://aidanhogan.com/teaching/tools/cc3201/vm-test-jdbc.zip|vm-test-jdbc.zip]]) con una clase que usa JDBC para conectar a la base de datos de grupo 18 (como un ejemplo). Hay que cambiar el puerto y la consulta (o crear una tabla ''test.hello'' en tu base de datos). También, hay que configurar Postgres y agregar una contraseña para el usuario ''cc3201'' en Postgres ... | ''ls'' muestra ''17'', así que los archivos están en ''/etc/postgresql/17/main/''. ''ss -ltn'' lista los puertos en que hay un programa escuchando (''l'': //listening//, ''t'': TCP, ''n'': números en vez de nombres) y ''grep 5432'' deja solo las líneas de Postgres. Por ahora dice ''127.0.0.1:5432'' y ''[::1]:5432''; es decir, Postgres escucha solo en localhost. |
| |
| ==== Configurar Postgres ==== | ===== Paso 3: pg_hba.conf ===== |
| |
| Ahora tenemos que configurar Postgres para permitir conexiones externas. Tenemos que cambiar la configuración en dos archivos: | Abran el primer archivo: |
| |
| <code> | <code> |
| sudo vim /etc/postgresql/9.6/main/pg_hba.conf | sudo vim /etc/postgresql/17/main/pg_hba.conf |
| </code> | </code> |
| |
| En este archivo, por defecto, permite solo conexiones desde localhost. Específicamente, dice: | (Si la ruta está mal, vim abre un archivo vacío y en la última línea aparece ''[New DIRECTORY]''. En ese caso salgan con '':q!'' y revisen el número de versión del paso 2.) |
| | |
| | Cada línea que no empieza con ''#'' es una regla, con cinco columnas: tipo de conexión (''local'' dentro de la máquina, ''host'' por red), base de datos, rol, dirección de origen y método de autenticación. Casi al final del archivo están las reglas para conexiones por red: |
| |
| <code> | <code> |
| # IPv4 local connections: | # IPv4 local connections: |
| host all all 127.0.0.1/32 md5 | host all all 127.0.0.1/32 scram-sha-256 |
| # IPv6 local connections: | # IPv6 local connections: |
| host all all ::1/128 md5 | host all all ::1/128 scram-sha-256 |
| </code> | </code> |
| |
| Tenemos que cambiar eso a lo siguiente: | {{proyecto:servidor_ext_03_pg_hba_antes.png?direct&900|pg_hba.conf antes: solo 127.0.0.1 y ::1}} |
| | |
| | Estas dos reglas dicen "cualquier base y cualquier rol, pero solo desde esta misma máquina". Hay que dejarlas así: |
| |
| <code> | <code> |
| # IPv4 local connections: | # IPv4 local connections: |
| host all all 0.0.0.0/0 md5 | host all all 0.0.0.0/0 scram-sha-256 |
| # host all all 127.0.0.1/32 md5 | # host all all 127.0.0.1/32 scram-sha-256 |
| # IPv6 local connections: | # IPv6 local connections: |
| host all all ::0/0 md5 | host all all ::0/0 scram-sha-256 |
| # host all all ::1/128 md5 | # host all all ::1/128 scram-sha-256 |
| </code> | </code> |
| |
| ... y guardar el archivo. (''#'' indica un comentario, ''0.0.0.0/0'' indica permitir todo, ''::0/0'' igualmente). | {{proyecto:servidor_ext_04_pg_hba_despues.png?direct&900|pg_hba.conf después: cualquier dirección, con contraseña}} |
| |
| El segundo archivo que tenemos que cambiar es: | Las reglas nuevas aceptan conexiones desde cualquier dirección, siempre con contraseña (''scram-sha-256''). Las antiguas quedan como comentario (el ''#'' al comienzo hace que Postgres ignore la línea), por si quieren volver atrás. |
| | |
| | En vim, hay que presionar ''i'' para empezar a editar; luego, para guardar y salir, ''Esc'' y después '':wq'' [enter]. Si se perdieron, ''Esc'' y '':q!'' [enter] sale sin guardar. |
| | |
| | ===== Paso 4: postgresql.conf ===== |
| | |
| | El segundo archivo es: |
| |
| <code> | <code> |
| sudo vim /etc/postgresql/9.6/main/postgresql.conf | sudo vim /etc/postgresql/17/main/postgresql.conf |
| </code> | </code> |
| |
| En ese archivo, hay que cambiar ''localhost'' con ''*'' para escuchar a cada IP (no solo localhost): | Es un archivo largo. Para encontrar la línea, en vim escriban ''/listen_addresses'' y apreten Enter (el ''/'' busca texto). Viene así: |
| |
| <code> | <code> |
| listen_addresses = '*' # what IP address(es) to listen on; | #listen_addresses = 'localhost' # what IP address(es) to listen on; |
| </code> | </code> |
| |
| ... y guardar el archivo. | {{proyecto:servidor_ext_05_listen_antes.png?direct&900|listen_addresses viene comentado}} |
| |
| Finalmente, hay que recargar la configuración de Postgres. Entonces, en ''psql'', ejecuta: | Hay que borrar el ''#'' del comienzo (si no, la línea sigue siendo un comentario y Postgres usa el valor por defecto, ''localhost'') y cambiar ''localhost'' por ''*'', que significa "escuchar en todas las direcciones de la máquina": |
| |
| <code>SELECT pg_reload_conf();</code> | <code> |
| | listen_addresses = '*' # what IP address(es) to listen on; |
| | </code> |
| | |
| | {{proyecto:servidor_ext_06_listen_despues.png?direct&900|listen_addresses sin # y con asterisco}} |
| | |
| | ... y guardar el archivo con ''Esc'' y '':wq''. |
| | |
| | ===== Paso 5: reiniciar Postgres ===== |
| |
| A veces no funciona (no sé porque) pero para estar seguro, quita ''psql'' y ejecuta: | Postgres lee estos archivos al arrancar, así que hay que reiniciarlo. Se hace desde la terminal del servidor, no desde ''psql'': |
| |
| <code> | <code> |
| sudo service postgresql stop | sudo systemctl restart postgresql |
| sudo service postgresql start | |
| </code> | </code> |
| |
| (Hemos reiniciado Postgres.) | ''systemctl'' es el programa que maneja los servicios de Linux (los programas que quedan corriendo de fondo, como Postgres). ''restart'' lo detiene y lo vuelve a partir; no imprime nada si funciona. |
| |
| ==== La Contraseña ==== | (En ''psql'' existe ''SELECT pg_reload_conf();'', que recarga la configuración sin reiniciar. No alcanza en este caso, porque ''listen_addresses'' solo cambia al reiniciar.) |
| |
| En el código de la prueba arriba (''vm-test-jdbc.zip''), pide la contraseña del usuario ''cc3201''. (//En general, no es una buena idea guardar una contraseña así en texto plano en el código fuente, pero para hacer una prueba, está bien ... si trabajaras para una empresa, sería imprescindible poner y leer la contraseña desde un archivo de configuración seguro.//) | Para revisar que quedó escuchando hacia afuera, repitan el ''ss'' del paso 2: |
| |
| De todos modos, tenemos que configurar la contraseña. No es la misma contraseña que la contraseña de SSH para ingresar al servidor. De hecho, por defecto, no hay una contraseña (en el servidor, Postgres usa los credenciales de SSH por defecto, pero JDBC (por ejemplo) va a conectarse directamente con Postres, no por SSH). | <code> |
| | ss -ltn | grep 5432 |
| | </code> |
| |
| Bueno, en ''psql'', hay que poner: | {{proyecto:servidor_ext_07_reinicio.png?direct&900|Antes del reinicio escucha en 127.0.0.1, después en 0.0.0.0}} |
| |
| <code>\password cc3201</code> | Tiene que aparecer ''0.0.0.0:5432''. Si aparece ''127.0.0.1:5432'', falta el reinicio o el cambio en ''postgresql.conf'' no quedó bien (revisen el ''#''). |
| | |
| | Si Postgres no arranca después del reinicio, lo más probable es un error de tipeo en uno de los dos archivos. ''sudo systemctl status postgresql'' muestra el estado, y ''sudo tail /var/log/postgresql/postgresql-17-main.log'' las últimas líneas del registro, donde aparece el archivo y la línea con el problema. |
| | |
| | ===== Los Puertos ===== |
| | |
| | Para conectarse con Postgres **desde otra máquina** (por ejemplo, un notebook), el puerto será ''55XX'' donde XX es el número de la máquina. Por ejemplo, desde afuera la máquina 6 se conecta por el puerto 5506 y la máquina 21 por el 5521. |
| | |
| | <code> |
| | hostname: cc3201.dcc.uchile.cl |
| | puerto: 55XX (donde XX es el número de la máquina) |
| | usuario: cc3201 |
| | base de datos: cc3201 |
| | contraseña: la que pusieron con \password |
| | </code> |
| | |
| | Para conectarse con Postgres desde la misma máquina (por ejemplo, desde una aplicación que corre en el servidor), el puerto será ''5432'' y el host será ''localhost''. El puerto ''55XX'' no va a funcionar dentro de la misma máquina, porque el reenvío de puertos solo funciona para conexiones que vienen de afuera. |
| | |
| | ===== Probar la conexión ===== |
| | |
| | Desde su notebook, si tienen ''psql'' instalado (en la máquina 40, por ejemplo): |
| | |
| | <code> |
| | psql -h cc3201.dcc.uchile.cl -p 5540 -U cc3201 cc3201 |
| | </code> |
| | |
| | ''-h'' es el //host// (a qué máquina conectarse), ''-p'' el puerto, ''-U'' el rol, y el último ''cc3201'' es la base de datos. Pide la contraseña de Postgres (la del paso 1): |
| |
| ... y ingresar una contraseña. Después, hay que poner la contraseña en el código de la prueba: | {{proyecto:servidor_ext_08_conexion_notebook.png?direct&900|Conexión desde el notebook por el puerto 5540}} |
| |
| <code>private static final String PASSWORD = "**ingresa**password**de**cc3201**aquí**";</code> | Si muestra ''cc3201=#'', la conexión externa funciona. La línea que empieza con ''SSL connection'' indica que la conexión va cifrada. Si la versión de ''psql'' de su notebook es distinta de la del servidor (en la imagen, 18 y 17), no hay problema. |
| |
| ==== Ejecutar La Prueba ==== | También pueden conectarse con DBeaver o pgAdmin: al crear la conexión, elijan PostgreSQL y usen los mismos datos de la sección anterior. |
| |
| Hay que cambiar el puerto y la contraseña y configurar todo arriba. La prueba asume que hay una tabla ''test.hello''; ejecuta la siguiente consulta: | Si algo falla, el mensaje de error indica qué falta: |
| |
| <code>SELECT * FROM test.hello</code> | ^ Mensaje ^ Qué revisar ^ |
| | | ''Connection refused'' | Postgres no está escuchando hacia afuera (el primer filtro). Revisen ''listen_addresses'' (sin ''#'') y reinicien con ''sudo systemctl restart postgresql''. | |
| | | ''no pg_hba.conf entry for host ...'' | Falta la línea con ''0.0.0.0/0'' en ''pg_hba.conf'' (el segundo filtro), o quedó comentada. Después de corregirla, reinicien. | |
| | | ''password authentication failed for user "cc3201"'' | La contraseña no coincide. Vuelvan a ponerla con ''\password cc3201'' dentro del servidor. | |
| | | La conexión se queda pegada un buen rato y después dice ''timeout expired'' | Probablemente usaron el puerto ''55XX'' desde dentro del servidor (ahí es ''localhost'' y ''5432''), o se equivocaron en el número de máquina. | |
| |
| Se puede crear esa tabla y agregar una tupla, o se puede cambiar la consulta en el código para hacer la prueba. | |