1. Introdução
Com o Private Service Connect, você pode criar endpoints particulares usando endereços IP internos globais na sua rede VPC. É possível atribuir nomes DNS a esses endereços IP internos com nomes significativos, como storage-pscendpoint.p.googleapis.com e bigtable-adsteam.p.googleapis.com. Em vez de enviar solicitações de API para endpoints de serviços públicos, como storage.googleapis.com, é possível enviar solicitações para o endpoint do Private Service Connect, que é particular e interno à sua rede VPC.
Esses nomes e endereços IP são internos à sua rede VPC e a qualquer rede local conectada a ela usando túneis do Cloud VPN ou anexos do Cloud Interconnect (VLANs).
É possível controlar qual tráfego vai para cada endpoint e demonstrar que o tráfego permanece no Google Cloud.
O que você vai aprender
- Casos de uso do Private Service Connect
- Requisitos de rede
- APIs compatíveis
- Criar um endpoint do Private Service Connect
- crie um bucket do Google Cloud Storage
- Criar e atualizar zonas particulares do Cloud DNS
- Criar um NAT GW para acessar googleapis públicas
- Criar e atualizar um arquivo de configuração BOTO
- Executar a lista da gsutil na VM1 resolvida em relação ao endpoint de serviço do PSC
- Executar a lista da gsutil na VM2 resolvida em googleapis.com público
- Usar o Tcpdump para validar a resolução de DNS
O que é necessário
- Conhecimento sobre o editor DNS, nano ou vi.
2. Casos de uso do Private Service Connect
É possível criar vários endpoints do Private Service Connect na mesma rede VPC. Não há limite de largura de banda para um endpoint específico. Como os endpoints do Private Service Connect usam endereços IP internos globais, eles podem ser usados por qualquer recurso na sua rede VPC.
Com vários endpoints, é possível especificar caminhos de rede diferentes usando o Cloud Router e regras de firewall.
- É possível criar regras de firewall para impedir que algumas VMs acessem as APIs do Google por um endpoint do Private Service Connect e, ao mesmo tempo, permitir que outras VMs tenham acesso.
- É possível ter uma regra de firewall em uma instância de VM que proíba todo o tráfego para a Internet. o tráfego enviado para endpoints do Private Service Connect ainda chega ao Google.
- Se você tiver hosts locais conectados a uma VPC usando um túnel do Cloud VPN ou um anexo do Cloud Interconnect (VLAN), poderá enviar algumas solicitações pelo túnel ou pela VLAN enquanto envia outras pela Internet pública. Essa configuração permite que você ignore o túnel ou a VLAN para serviços como o Google Livros, que não são compatíveis com o Acesso privado do Google. Para isso, crie um endpoint do Private Service Connect, divulgue os endereços IP do endpoint usando divulgações de rota personalizadas do Cloud Router e ative uma política de encaminhamento de entrada do Cloud DNS. O aplicativo pode enviar algumas solicitações pelo túnel do Cloud VPN ou pelo anexo do Cloud Interconnect (VLAN) usando o nome do endpoint do Private Service Connect e outras pela Internet usando o nome do DNS padrão.
- Se você conectar sua rede local à VPC usando vários anexos do Cloud Interconnect (VLANs), poderá enviar tráfego do local por uma VLAN e o restante em outra, como mostrado na figura 2. Isso permite que você use sua própria rede de longa distância em vez da rede do Google e controle a movimentação de dados para atender aos requisitos geográficos. Para criar essa configuração, crie dois endpoints do Private Service Connect. Crie uma divulgação de rota personalizada para o primeiro endpoint na sessão do BGP do Cloud Router que gerencia a primeira VLAN e crie uma divulgação de rota personalizada diferente para o segundo endpoint na sessão do BGP do Cloud Router que gerencia a segunda VLAN. Hosts locais configurados para usar o nome de endpoint do Private Service Connect enviam tráfego pelo anexo do Cloud Interconnect (VLAN) correspondente.
- Também é possível usar vários anexos do Cloud Interconnect (VLANs) em uma topologia ativa/ativa. Se você divulgar o mesmo endereço IP do endpoint do Private Service Connect usando divulgações de rota personalizadas para as sessões do BGP nos Cloud Routers que gerenciam as VLANs, os pacotes enviados dos sistemas locais para os endpoints serão roteados pelas VLANs usando o ECMP.
Figura 1. Ao configurar o Private Service Connect, o Cloud Router e hosts locais, é possível controlar qual anexo do Cloud Interconnect (VLAN) é usado para enviar tráfego às APIs do Google.
3. Requisitos de rede
Para usar o Private Service Connect, as instâncias de máquina virtual (VM) sem endereços IP externos precisam ter a interface principal em uma sub-rede com o Acesso privado do Google ativado.
Uma VM com um endereço IP externo pode acessar serviços e APIs do Google usando endpoints do Private Service Connect, mesmo que o Acesso privado do Google não esteja ativado na sub-rede. A conectividade com o endpoint do Private Service Connect permanece dentro da rede do Google.
Os endpoints do Private Service Connect não são acessíveis em redes VPC com peering.
APIs compatíveis
Ao criar um endpoint do Private Service Connect, você escolhe qual pacote de APIs precisa acessar: all-apis ou vpc-sc.
Os pacotes de APIs dão acesso às mesmas APIs disponíveis nos VIPs de Acesso privado do Google.
- O pacote all-apis oferece acesso às mesmas APIs que private.googleapis.com.
- O pacote vpc-sc fornece acesso às mesmas APIs que restricted.googleapis.com.
4. Topologia e codelabs caso de uso
Figura 1 - Topologia do codelab
Caso de uso do codelab:
Nosso cliente exige uma combinação de acesso privado (interconexão) e googleapis público para transferência de dados do armazenamento em nuvem. Para atender aos requisitos dos nossos clientes, vamos implantar o Private Service Connect, que consiste em um endereço /32 exclusivo, configuração BOTO e atualizações de registros DNS. A máquina virtual 1 vai utilizar o PSC para acessar o bucket do armazenamento em nuvem. Já a VM2 vai usar intervalos de IP públicos de googleapis.com pelo NAT GW.
Todos os aspectos do laboratório são implantados no Google Cloud Platform, mas o mesmo caso de uso se aplica a implantações de nuvem híbrida que exigem separação do tráfego.
5. Configuração e requisitos
Configuração de ambiente autoguiada
- Faça login no Console do Cloud e crie um novo projeto ou reutilize um existente. Crie uma se você ainda não tiver uma conta do Gmail ou do G Suite.
Lembre-se do código do projeto, um nome exclusivo em todos os projetos do Google Cloud. O nome acima já foi escolhido e não servirá para você. Faremos referência a ele mais adiante neste codelab como PROJECT_ID
.
- Em seguida, será necessário ativar o faturamento no Console do Cloud para usar os recursos do Google Cloud.
A execução deste codelab não será muito cara, se for o caso. Siga todas as instruções na seção "Limpeza", que orienta você sobre como encerrar recursos para não incorrer em cobranças além deste tutorial. Novos usuários do Google Cloud estão qualificados para o programa de avaliação gratuita de US$ 300.
Inicie o Cloud Shell
Embora o Google Cloud e o Spanner possam ser operados remotamente do seu laptop, neste codelab usaremos o Google Cloud Shell, um ambiente de linha de comando executado no Cloud.
No Console do GCP, clique no ícone do Cloud Shell na barra de ferramentas localizada no canto superior direito:
O provisionamento e a conexão com o ambiente levarão apenas alguns instantes para serem concluídos: Quando o processamento for concluído, você verá algo como:
Essa máquina virtual contém todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Todo o trabalho neste laboratório pode ser feito apenas com um navegador.
6. Antes de começar
Ativar APIs
No Cloud Shell, verifique se o ID do projeto está configurado
gcloud config list project gcloud config set project [YOUR-PROJECT-NAME] projectname=YOUR-PROJECT-NAME echo $projectname
Ative todos os serviços necessários
gcloud services enable compute.googleapis.com gcloud services enable servicedirectory.googleapis.com gcloud services enable dns.googleapis.com
7. Criar rede VPC
Rede VPC
No Cloud Shell
gcloud compute networks create psc-lab --subnet-mode custom
Saída
Created NAME SUBNET_MODE BGP_ROUTING_MODE IPV4_RANGE GATEWAY_IPV4 psc-lab CUSTOM REGIONAL
Criar sub-rede
No Cloud Shell
gcloud compute networks subnets create psclab-subnet \ --network psc-lab --range 10.0.0.0/24 --region us-central1
–enable-private-ip-google-access
Saída
Created NAME REGION NETWORK RANGE psclab-subnet us-central1 psc-lab 10.0.0.0/24
Criar regras de firewall
No Cloud Shell
gcloud compute firewall-rules create psclab-ssh \ --network psc-lab --allow tcp:22 --source-ranges=35.235.240.0/20
Saída
NAME NETWORK DIRECTION PRIORITY ALLOW DENY DISABLED psclab-ssh psc-lab INGRESS 1000 tcp:22 False
Criar instância do Cloud NAT
Criar Cloud Router
No Cloud Shell
gcloud compute routers create crnat \ --network psc-lab \ --asn 65000 \ --region us-central1
Criar o Cloud NAT
No Cloud Shell
gcloud compute routers nats create cloudnat \ --router=crnat \ --auto-allocate-nat-external-ips \ --nat-all-subnet-ip-ranges \ --enable-logging \ --region us-central1
8. Criar endpoint do Private Service Connect
Ao configurar o IP <pscendpointip>
do endpoint do Private Service Connect, você precisa fornecer um endereço IP exclusivo não definido na sua VPC.
No Cloud Shell
gcloud beta compute addresses create psc-ip \ --global \ --purpose=PRIVATE_SERVICE_CONNECT \ --addresses=<pscendpointip> \ --network=psc-lab
Armazenar "pscendpointip" durante o laboratório
(gcloud compute addresses list --filter=name:psc-ip --format="value(address)") pscendpointip=$(gcloud compute addresses list --filter=name:psc-ip --format="value(address)") echo $pscendpointip
Crie uma regra de encaminhamento para conectar o endpoint aos serviços e APIs do Google.
No Cloud Shell
gcloud beta compute forwarding-rules create pscendpoint \ --global \ --network=psc-lab \ --address=psc-ip \ --target-google-apis-bundle=all-apis
Liste os endpoints configurados do Private Service Connect
No Cloud Shell
gcloud compute forwarding-rules list \ --filter target="(all-apis OR vpc-sc)" --global
Descrever os endpoints configurados do Private Service Connect
No Cloud Shell
gcloud compute forwarding-rules describe \ pscendpoint --global
9. Criar um bucket
Crie um bucket do Cloud Storage e substitua BUCKET_NAME por um nome globalmente exclusivo de sua preferência.
No Cloud Shell
gsutil mb -l us-central1 -b on gs://BUCKET_NAME
Armazenar "BUCKET_NAME" durante o laboratório
BUCKET_NAME=YOUR BUCKET NAME echo $BUCKET_NAME
10. Configuração de DNS
Imagine que você tem um aplicativo que usa o Google Cloud Storage. Sem o Private Service Connect, seus aplicativos podem se conectar a "storage.googleapis.com", que, por padrão, é resolvido para algum endereço público. Com o Private Service Connect, é possível criar e usar nomes como "storage-psclab.p.googleapis.com". O nome e os endereços são particulares da sua rede VPC e de qualquer rede local anexada.
O Private Service Connect para DNS segue a convenção de nomenclatura, SERVICE-ENDPOINT.p.googleapis.com. No exemplo acima, "storage" é o SERVICE & "psclab" é o ENDPOINT. É obrigatório incluir "-" entre SERVICE e ENDPOINT.
Para acessar o Cloud Storage usando o endpoint do Private Service Connect, crie um registro DNS (A) storage-psclab.p.googleapis.com que aponte para o endereço IP do endpoint do Private Service Connect.
Criar zona particular de DNS
gcloud dns --project=$projectname managed-zones create psc-dns-zone --description="" --dns-name="p.googleapis.com." --visibility="private" --networks="psc-lab"
Criar registro DNS A
gcloud dns --project=$projectname record-sets transaction start --zone=psc-dns-zone gcloud dns --project=$projectname record-sets transaction add $pscendpointip --name=storage-pscendpoint.p.googleapis.com. --ttl=300 --type=A --zone=psc-dns-zone gcloud dns --project=$projectname record-sets transaction execute --zone=psc-dns-zone
11. Criar máquinas virtuais
Criar uma máquina virtual (psc-instance-1) usada para validar o Private Service Connect
No Cloud Shell
gcloud compute instances create psc-instance-1 \ --subnet psclab-subnet \ --zone us-central1-a \ --image=centos-7-v20210122 \ --image-project=centos-cloud \ --no-address \ --metadata=startup-script=yum\ install\ tcpdump\ -y$'\n'yum\ install\ bind-utils\ -y$'\n'yum\ install\ nano\ -y
Faça login na instância de VM (psc-instance-1).
Conecte-se via SSH à VM pelo Cloud Shell
gcloud compute ssh --zone "us-central1-a" "psc-instance-1" --project "$projectname"
Para criar outros terminais do Cloud Shell, clique em + (captura de tela abaixo) três vezes.
Criar uma máquina virtual (psc-instance-2) usada para validar o Googleapis públicos
Da guia 2
gcloud compute instances create psc-instance-2 \ --subnet psclab-subnet \ --zone us-central1-a \ --image=centos-7-v20210122 \ --image-project=centos-cloud \ --no-address \ --metadata=startup-script=yum\ install\ tcpdump\ -y$'\n'yum\ install\ bind-utils\ -y$'\n'yum\ install\ nano\ -y
Na guia 2, acesse a VM usando o Cloud Shell
gcloud config list project gcloud config set project [YOUR-PROJECT-NAME] projectname=YOUR-PROJECT-NAME echo $projectname gcloud compute ssh --zone "us-central1-a" "psc-instance-2" --project "$projectname"
Na guia 3, use SSH para se conectar a psc-instance-1 pelo Cloud Shell
gcloud config list project gcloud config set project [YOUR-PROJECT-NAME] projectname=YOUR-PROJECT-NAME echo $projectname gcloud compute ssh --zone "us-central1-a" "psc-instance-1" --project "$projectname"
Na guia 4, acesse "psc-instance-2" com SSH via Cloud Shell
gcloud config list project gcloud config set project [YOUR-PROJECT-NAME] projectname=YOUR-PROJECT-NAME echo $projectname gcloud compute ssh --zone "us-central1-a" "psc-instance-2" --project "$projectname"
12. Verificar o comportamento atual do Gsutil
Na aba 4 (psc-instance-2), inicie o tcpdump e monitore o tráfego DNS.
sudo tcpdump -vv -i eth0 port 53
Inspecione a busca DNS do bucket de armazenamento na guia 2 (psc-instance-2)
BUCKET_NAME=YOUR BUCKET NAME echo $BUCKET_NAME gsutil -D ls gs://$BUCKET_NAME
Inspecione a depuração da gsutil. HOST storage.googleapis.com é usado para resolução de DNS
<snip> send: 'GET /storage/v1/b/$BUCKET_NAME/o?delimiter=%2F&projection=noAcl&versions=False&fields=prefixes%2CnextPageToken%2Citems%2Fname&alt=json&maxResults=1000 HTTP/1.1\r\nHost: storage.googleapis.com\r\ncontent-length: 0\r\nauthorization: Bearer ya29.c.KpkB7wfaMjfc_WXEKCeNF4Md0fEHnfDU7tqBf3cd0u43yEmYXqj8fX_X5wWdNdDVH6k1EkjeAeIJDzKGvyjPOkf1Io2kVeUqYX69sDv53huW1NslffjAHKchbZ0CP3Cg83TS3Pa55jLcuE0TLbYycVrgSbD3H90LaapUGbWD3kj4IsJLf9J8R98Bqobu8HZwwqk92hlZ4zVzRqOM\r\naccept-encoding: gzip, deflate\r\naccept: application/json\r\nuser-agent: apitools Python/2.7.5 gsutil/4.57 (linux2) analytics/disabled interactive/True command/ls google-cloud-sdk/324.0.0\r\n\r\n' reply: 'HTTP/1.1 200 OK\r\n' <snip>
Na aba 4 (psc-instance-2), verifique se os registros A DNS públicos do GoogleAPI.com são usados para acessar o bucket de armazenamento.
metadata.google.internal.domain > psc-instance-2.c.yourprojectname.internal.33973: [udp sum ok] 36442 q: A? storage.googleapis.com. 11/0/0 storage.googleapis.com. A 108.177.111.128, storage.googleapis.com. A 142.250.128.128, storage.googleapis.com. A 74.125.70.128, storage.googleapis.com. A 74.125.201.128, storage.googleapis.com. A 64.233.183.128, storage.googleapis.com. A 173.194.198.128, storage.googleapis.com. A 172.217.219.128, storage.googleapis.com. A 142.250.136.128, storage.googleapis.com. A 209.85.234.128, storage.googleapis.com. A 172.217.212.128, storage.googleapis.com. A 172.217.214.128
13. Modificar o comportamento do Gsutil
Lembre-se de que, em uma etapa anterior, você criou uma zona DNS particular e um registro A mapeado para o endereço IP do endpoint do PSC. Na etapa a seguir, controlaremos como a gsutil se comporta atualizando o arquivo BOTO da VM em psc-instance-1.
Confira a configuração de BOTO padrão do terminal da instância de VM na guia 1 (psc-instance-1)
[psc-instance ~]$ more /etc/boto.cfg
Saída (seu project_id será diferente)
[GSUtil] default_project_id = 234086459238 default_api_version = 2 [GoogleCompute] service_account = default
Atualize a configuração BOTO usando o nano ou o VI Editor. Copie e cole todas as entradas.
Exemplo: sudo nano /etc/boto.cfg
ou
Exemplo: sudo vi /etc/boto.cfg
Na guia 1 do terminal da instância de VM(psc-instance-1)
[Credentials] gs_host = storage-pscendpoint.p.googleapis.com gs_host_header = storage.googleapis.com gs_json_host = storage-pscendpoint.p.googleapis.com gs_json_host_header = www.googleapis.com
Validar a configuração. A ordem de [Credenciais] é fundamental para a busca DNS.
more /etc/boto.cfg [Credentials] gs_host = storage-pscendpoint.p.googleapis.com gs_host_header = storage.googleapis.com gs_json_host = storage-pscendpoint.p.googleapis.com gs_json_host_header = www.googleapis.com [GSUtil] default_project_id = 234086459238 default_api_version = 2 [GoogleCompute] service_account = default
14. Verificar o comportamento atualizado de pesquisa do gsutil
Na aba 3 (psc-instance-1), inicie o tcpdump e monitore o tráfego DNS.
sudo tcpdump -vv -i eth0 port 53
Inspecione a pesquisa gsutil do bucket de armazenamento na guia 1 (psc-instance-1)
BUCKET_NAME=YOUR BUCKET NAME echo $BUCKET_NAME gsutil -D ls gs://$BUCKET_NAME
Os registros de depuração confirmam que o bucket de armazenamento pode ser acessado pelo endpoint "pscendpoint" do Private Service Connect
Saída:
<snip> INFO 0131 22:14:18.795986 base_api.py] Making http GET to https://storage-pscendpoint.p.googleapis.com/storage/v1/b/$BUCKET_NAME/o?delimiter=%2F&projection=noAcl&versions=False&fields=prefixes%2CnextPageToken%2Citems%2Fname&alt=json&maxResults=1000 INFO 0131 22:14:18.796415 base_api.py] Headers: {u'Host': 'www.googleapis.com', 'accept': 'application/json', 'accept-encoding': 'gzip, deflate', 'content-length': '0', 'user-agent': 'apitools Python/2.7.5 gsutil/4.57 (linux2) analytics/disabled interactive/True command/ls google-cloud-sdk/324.0.0'} INFO 0131 22:14:18.796502 base_api.py] Body: (none) connect: (storage-pscendpoint.p.googleapis.com, 443) send: 'GET /storage/v1/b/psc-bucket/o?delimiter=%2F&projection=noAcl&versions=False&fields=prefixes%2CnextPageToken%2Citems%2Fname&alt=json&maxResults=1000 HTTP/1.1\r\ncontent-length: 0\r\naccept-encoding: gzip, deflate\r\naccept: application/json\r\nuser-agent: apitools Python/2.7.5 gsutil/4.57 (linux2) analytics/disabled interactive/True command/ls google-cloud-sdk/324.0.0\r\nhost: www.googleapis.com\r\nauthorization: Bearer ya29.c.KpkB7wd3XWiYeRyTuth5_HPlNV-hPwc2Nn7RSIeMpzrpa_j4EsMPl2m_mDGKAcGHvYIgiC5bT2UVQirAPpSbbpToa6G6lkaBbH5SZwHwgNXYfisp5Ww1UjXe4rTa69a_Wp0WesafcwPNnYzDo3xf5VGh3iGhySA04kTXuyT--MgOU8U-XLII2LJQxUWlV8KEdrvyCuqRb-jsDdk_\r\n\r\n' reply: 'HTTP/1.1 200 OK\r\n' <snip>
Na aba 3 (psc-instance-1), verifique se o IP do endpoint do PSC é o registro A do DNS usado ao tentar acessar o bucket de armazenamento.
@psc-instance-1 ~]$ sudo tcpdump -vv -i eth0 port 53 tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 05:02:33.936256 IP (tos 0x0, ttl 64, id 55416, offset 0, flags [DF], proto UDP (17), length 82) psc-instance-1.c.yourprojectname.internal.42296 > metadata.google.internal.domain: [bad udp cksum 0x5e4e -> 0xcceb!] 34796+ A? storage-pscendpoint.p.googleapis.com. (54) 05:02:33.936269 IP (tos 0x0, ttl 64, id 55417, offset 0, flags [DF], proto UDP (17), length 82) psc-instance-1.c.yourprojectname.internal.42296 > metadata.google.internal.domain: [bad udp cksum 0x5e4e -> 0x3ebd!] 5632+ AAAA? storage-pscendpoint.p.googleapis.com. (54) 05:02:33.944018 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto UDP (17), length 98) metadata.google.internal.domain > psc-instance-1.c.yourprojectname.42296: [udp sum ok] 34796 q: A? storage-pscendpoint.p.googleapis.com. 1/0/0 storage-pscendpoint.p.googleapis.com. A 10.10.110.10 (70) 05:02:33.946005 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto UDP (17), length 175)
Verifique se o IP do endpoint do Private Service Connect agora é usado para resolução de DNS
Da guia1
nslookup storage-pscendpoint.p.googleapis.com
Saída
@psc-instance ~]$ nslookup storage-pscendpoint.p.googleapis.com Server: 169.254.169.254 Address: 169.254.169.254#53 Non-authoritative answer: Name: storage-pscendpoint.p.googleapis.com Address: <pscip>
15. Etapas de limpeza
Sair da instância da VM (todas as guias)
exit
Exclua os componentes do laboratório em um único terminal do Cloud Shell
gcloud compute routers nats delete cloudnat --router=crnat --region=us-central1 --quiet gcloud compute routers delete crnat --region=us-central1 --quiet gcloud beta compute forwarding-rules delete pscendpoint --global --quiet gcloud beta compute addresses delete psc-ip --global --quiet gsutil rm -r gs://$BUCKET_NAME gcloud compute instances delete psc-instance-1 --zone=us-central1-a --quiet gcloud compute instances delete psc-instance-2 --zone=us-central1-a --quiet gcloud compute firewall-rules delete psclab-ssh --quiet gcloud compute networks subnets delete psclab-subnet --region us-central1 --quiet gcloud compute networks delete psc-lab --quiet
No console, verifique se você está visualizando o projeto correto e selecione Serviços de rede → Cloud DNS
Identificar e clique em "psc-dns-zone".
Selecione o conjunto de registros "storage-pscendpoint.p.googleapis.com" e clique em "Excluir conjuntos de registros"
Clique em "Excluir zona" para concluir a limpeza do laboratório
16. Parabéns!
Parabéns por concluir o codelab.
O que vimos
- Casos de uso do Private Service Connect
- Requisitos de rede
- APIs compatíveis
- Criou um endpoint do Private Service Connect
- Criou um bucket do Cloud Storage
- Criar zonas particulares do Cloud DNS
- Arquivo de configuração BOTO atualizado
- Criou um NAT GW
- Execute a lista da gsutil na VM1 que é resolvida em relação ao endpoint de serviço do PSC
- Executar a lista gsutil na VM2 que se resolve em googleapis.com público
- Usar o Tcpdump para validar a resolução de DNS