Como você precisa rotear com base no hostname em vez de port, a solução iptables do NAT para o tráfego para as VMs está fora.
O que resta é a execução de um servidor da Web no modo de proxy reverso, que lê o cabeçalho do host de solicitação e os proxies para os diferentes IPs privados com base no cabeçalho da solicitação.
A configuração exata dependerá de qual servidor da Web você usará e de qual servidor da Web você selecionará dependerá de quais recursos são necessários (SSL?), além de preferências pessoais. Deixe-me saber qual servidor da Web você prefere e posso editar a resposta para incluir um exemplo de configuração, se necessário.
edit: Configuração básica do nginx:
http {
# ...existing config basics... server_name, NOT servername
server {
listen 80;
server_name git.example.com;
location / {
# git server IP below:
proxy_pass http://10.x.x.x:80/;
# re-send the host header - this may not be necessary
proxy_set_header Host $host;
# set the X-Forwarded-For header, so that the public IP of the client is available to the backend server
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 80;
server_name psql.example.com;
location / {
# psql server IP below:
proxy_pass http://10.x.x.x:80/;
# re-send the host header - this may not be necessary
proxy_set_header Host $host;
# set the X-Forwarded-For header, so that the public IP of the client is available to the backend server
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 80;
server_name www.example.com;
location / {
# www server IP below:
proxy_pass http://10.x.x.x:80/;
# re-send the host header - this may not be necessary
proxy_set_header Host $host;
# set the X-Forwarded-For header, so that the public IP of the client is available to the backend server
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}