forked from erjosito/azcli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dns_fwding.azcli
774 lines (731 loc) · 47.4 KB
/
dns_fwding.azcli
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
############################################################################
# Created by Jose Moreno
# December 2021
#
# The script creates an AzFW and configures as DNS server of a VNet.
# The DNS server of the firewall is Azure DNS.
# An Azure DNS Forwarder is configured to forward requests for a corp domain
# to another DNS server running on a VM (dnsmasq).
############################################################################
# Control variables
create_azfw=yes # Whether an AzFW is created in the hub with DNS configured
create_onpremdns=yes # Whether a dnsmasq server is configured to simulate an onprem server
create_spokes=yes # Create spokes
create_onprem=yes # Create VPN GW and simulate onprem
# Variables
# Note: '10.0.1.0/24;10.0.2.0/24;10.0.3.0/24' are reserved IPs!!!!!
rg=dnsresolver
location=westeurope
vnet_name=hub
vnet_prefix=192.168.0.0/16
azfw_name=azfwdns
azfw_policy_name=azfwdnspolicy
azfw_pip_name="${azfw_name}-pip"
azfw_subnet_name=AzureFirewallSubnet
azfw_subnet_prefix=192.168.1.0/24
vm_size=Standard_B1s
client_vm_name=clientvm
client_vm_pip_name="${client_vm_name}-pip"
client_subnet_name=vm
client_subnet_prefix=192.168.10.0/24
gw_subnet_prefix=192.168.0.0/24
dns_vm_name=dnsserver
dns_vm_pip_name="${dns_vm_name}-pip"
dns_subnet_name=dns-vm
dns_subnet_prefix=192.168.53.0/24
sample_domain=contoso.com
sample_name=test
sample_fqdn="${sample_name}.${sample_domain}"
sample_ip=1.2.3.4
resolver_in_subnet_name=resolverin
resolver_in_subnet_prefix=192.168.101.0/28
resolver_out_subnet_name=resolverout
resolver_out_subnet_prefix=192.168.101.16/28
resolver_name=hubresolver
in_ep_name=hubin
out_ep_name=hubout
fwd_ruleset_name=hubfwdruleset
fwd_rule_name=contosocorp
private_dns_zone=contoso.corp
private_dns_host=test
private_dns_fqdn="${private_dns_host}.${private_dns_zone}"
private_dns_ip="5.6.7.8"
spoke1_vnet_name=spoke1
spoke1_vnet_prefix='10.1.1.0/24'
spoke1_subnet_name=vm
spoke1_subnet_prefix='10.1.1.0/26'
spoke1_vm_name=spoke1clientvm
spoke1_vm_pip_name="${spoke1_vm_name}-pip"
spoke1_resolver_in_subnet_name=resolverin
spoke1_resolver_in_subnet_prefix=10.1.1.64/28
spoke1_resolver_out_subnet_name=resolverout
spoke1_resolver_out_subnet_prefix=10.1.1.80/28
spoke2_vnet_name=spoke2
spoke2_vnet_prefix='10.1.2.0/24'
spoke2_subnet_name=vm
spoke2_subnet_prefix='10.1.2.0/26'
spoke2_vm_name=spoke2clientvm
spoke2_vm_pip_name="${spoke2_vm_name}-pip"
spoke2_resolver_in_subnet_name=resolverin
spoke2_resolver_in_subnet_prefix=10.1.2.64/28
spoke2_resolver_out_subnet_name=resolverout
spoke2_resolver_out_subnet_prefix=10.1.2.80/28
onprem_vnet_name=nva
onprem_vnet_prefix=172.16.0.0/16
nva_subnet_name=nva
nva_subnet_prefix=172.16.0.0/24
nva_name=mynva
nva_pip_name="${nva_name}-pip"
nva_vm_size=Standard_B1s
nva_asn=65001
vpngw_name=vpnvng
vpn_psk='Microsoft123!'
# Sets the variables for a previously created environment
function set_variables() {
if [[ "$create_azfw" == "yes" ]]
then
azfw_private_ip=$(az network firewall show -n $azfw_name -g $rg -o tsv --query 'ipConfigurations[0].privateIpAddress')
echo "Azure Firewall's private IP address: $azfw_private_ip"
fi
client_vm_pip=$(az network public-ip show -n $client_vm_pip_name -g $rg --query ipAddress -o tsv)
client_vm_nic_id=$(az vm show -n $client_vm_name -g $rg --query 'networkProfile.networkInterfaces[0].id' -o tsv)
client_vm_privateip=$(az network nic show --ids $client_vm_nic_id --query 'ipConfigurations[0].privateIpAddress' -o tsv)
echo "Hub client VM addresses: $client_vm_pip, $client_vm_privateip"
if [[ "$create_spokes" == "yes" ]]
then
spoke1_vm_pip=$(az network public-ip show -n $spoke1_vm_pip_name -g $rg --query ipAddress -o tsv)
spoke1_vm_nic_id=$(az vm show -n $spoke1_vm_name -g $rg --query 'networkProfile.networkInterfaces[0].id' -o tsv)
spoke1_vm_privateip=$(az network nic show --ids $spoke1_vm_nic_id --query 'ipConfigurations[0].privateIpAddress' -o tsv)
echo "Spoke1 client VM addresses: $spoke1_vm_pip, $spoke1_vm_privateip"
spoke2_vm_pip=$(az network public-ip show -n $spoke2_vm_pip_name -g $rg --query ipAddress -o tsv)
spoke2_vm_nic_id=$(az vm show -n $spoke2_vm_name -g $rg --query 'networkProfile.networkInterfaces[0].id' -o tsv)
spoke2_vm_privateip=$(az network nic show --ids $spoke2_vm_nic_id --query 'ipConfigurations[0].privateIpAddress' -o tsv)
echo "Spoke2 client VM addresses: $spoke2_vm_pip, $spoke2_vm_privateip"
fi
if [[ "$create_onprem" == "yes" ]]
then
nva_pip_ip=$(az network public-ip show -n $nva_pip_name -g $rg --query ipAddress -o tsv)
nva_nic_id=$(az vm show -n $nva_name -g "$rg" --query 'networkProfile.networkInterfaces[0].id' -o tsv)
nva_private_ip=$(az network nic show --ids $nva_nic_id --query 'ipConfigurations[0].privateIpAddress' -o tsv)
echo "Onprem NVA addresses: $nva_pip_ip, $nva_private_ip"
fi
if [[ "$create_onpremdns" == "yes" ]] && [[ "$create_onprem" == "no" ]]
then
dns_vm_pip=$(az network public-ip show -n $dns_vm_pip_name -g $rg --query ipAddress -o tsv)
dns_vm_nic_id=$(az vm show -n $dns_vm_name -g $rg --query 'networkProfile.networkInterfaces[0].id' -o tsv)
dns_vm_privateip=$(az network nic show --ids $dns_vm_nic_id --query 'ipConfigurations[0].privateIpAddress' -o tsv)
echo "DNS server in hub IP addresses: $dns_vm_pip, $dns_vm_privateip"
fi
in_ep_ip=$(az dns-resolver inbound-endpoint show --dns-resolver-name $resolver_name --name $in_ep_name -g $rg --query 'ipConfigurations[0].privateIpAddress' -o tsv)
echo "Private resolver's inbound endpoint IP: $in_ep_ip"
}
# Updates the SSH key for a single VM, specified in the first argument
function update_ssh_key() {
vm_name=$1
user=$(whoami)
echo "Updating SSH key for VM $vm_name and user $user..."
az vm user update -g $rg -u $user -n $vm_name --ssh-key-value "$(< ~/.ssh/id_rsa.pub)" -o none
}
# Updates the SSH keys of all VMs in this lab
function update_all_ssh_keys() {
update_ssh_key $client_vm_name
if [[ "$create_spokes" == "yes" ]]
then
update_ssh_key $spoke1_vm_name
update_ssh_key $spoke2_vm_name
fi
if [[ "$create_onprem" == "yes" ]]
then
update_ssh_key $nva_name
fi
if [[ "$create_onpremdns" == "yes" ]] && [[ "$create_onprem" == "no" ]]
then
update_ssh_key $dns_vm_name
fi
}
# RG and vnets
echo "Creating RG and VNet..."
az group create -n $rg -l $location -o none
az network vnet create -n $vnet_name -g $rg --address-prefixes $vnet_prefix --subnet-name $azfw_subnet_name --subnet-prefixes $azfw_subnet_prefix -o none
az network vnet subnet create -n $client_subnet_name --vnet-name $vnet_name -g $rg --address-prefixes $client_subnet_prefix -o none
az network vnet subnet create -n $dns_subnet_name --vnet-name $vnet_name -g $rg --address-prefixes $dns_subnet_prefix -o none
az network vnet subnet create -n $resolver_in_subnet_name --vnet-name $vnet_name -g $rg --address-prefixes $resolver_in_subnet_prefix -o none
az network vnet subnet create -n $resolver_out_subnet_name --vnet-name $vnet_name -g $rg --address-prefixes $resolver_out_subnet_prefix -o none
if [[ "$create_spokes" == "yes" ]]
then
# Spoke 1
az network vnet create -n $spoke1_vnet_name -g $rg --address-prefixes $spoke1_vnet_prefix --subnet-name $spoke1_subnet_name --subnet-prefixes $spoke1_subnet_prefix -o none
az network vnet peering create -n hubtospoke1 -g $rg --vnet-name $vnet_name --remote-vnet $spoke1_vnet_name --allow-vnet-access --allow-forwarded-traffic -o none
az network vnet peering create -n spoke1tohub -g $rg --vnet-name $spoke1_vnet_name --remote-vnet $vnet_name --allow-vnet-access --allow-forwarded-traffic -o none
# az network vnet subnet create -n $spoke1_resolver_in_subnet_name --vnet-name $spoke1_vnet_name -g $rg --address-prefixes $spoke1_resolver_in_subnet_prefix -o none
# az network vnet subnet create -n $spoke1_resolver_out_subnet_name --vnet-name $spoke1_vnet_name -g $rg --address-prefixes $spoke1_resolver_out_subnet_prefix -o none
# Spoke 2
az network vnet create -n $spoke2_vnet_name -g $rg --address-prefixes $spoke2_vnet_prefix --subnet-name $spoke2_subnet_name --subnet-prefixes $spoke2_subnet_prefix -o none
az network vnet peering create -n hubtospoke2 -g $rg --vnet-name $vnet_name --remote-vnet $spoke2_vnet_name --allow-vnet-access --allow-forwarded-traffic -o none
az network vnet peering create -n spoke2tohub -g $rg --vnet-name $spoke2_vnet_name --remote-vnet $vnet_name --allow-vnet-access --allow-forwarded-traffic -o none
# az network vnet subnet create -n $spoke2_resolver_in_subnet_name --vnet-name $spoke2_vnet_name -g $rg --address-prefixes $spoke2_resolver_in_subnet_prefix -o none
# az network vnet subnet create -n $spoke2_resolver_out_subnet_name --vnet-name $spoke2_vnet_name -g $rg --address-prefixes $spoke2_resolver_out_subnet_prefix -o none
fi
# Private DNS Zone
echo "Creating private DNS Zone..."
az network private-dns zone create -n $private_dns_zone -g $rg -o none
az network private-dns record-set a add-record --record-set-name $private_dns_host -z $private_dns_zone -g $rg -a $private_dns_ip -o none
az network private-dns link vnet create -g $rg -z $private_dns_zone -n $vnet_name --virtual-network $vnet_name --registration-enabled false -o none
# Alternatively, create the link with autoregistration
# az network private-dns link vnet delete -g $rg -z $private_dns_zone -n $vnet_name -y -o none
# az network private-dns link vnet create -g $rg -z $private_dns_zone -n $vnet_name --virtual-network $vnet_name --registration-enabled true -o none
# Create Azure Firewall
if [[ "$create_azfw" == "yes" ]]
then
echo "Creating Azure Firewall..."
az network firewall create -n $azfw_name -g $rg -l $location -o none
az network public-ip create -g $rg -n $azfw_pip_name --sku standard --allocation-method static -o none
az network firewall ip-config create -f $azfw_name -n azfw-ipconfig -g $rg --public-ip-address $azfw_pip_name --vnet-name $vnet_name -o none
az network firewall update -n $azfw_name -g $rg -o none
az network firewall policy create -n $azfw_policy_name -g $rg -o none
az network firewall update -n $azfw_name -g $rg --firewall-policy $azfw_policy_name -o none
az network firewall policy rule-collection-group create -n myrcg --policy-name $azfw_policy_name -g $rg --priority 1000 -o none
az network firewall policy rule-collection-group collection add-filter-collection --rule-type NetworkRule -g $rg --rcg-name myrcg --policy-name $azfw_policy_name \
--action Allow --collection-priority 1010 --name testnetrules --rule-name ifconfig --source-addresses '*' --destination-fqdns 'ifconfig.co' \
--ip-protocols Tcp --destination-ports 443 -o none
# az network firewall policy rule-collection-group collection rule add --rule-type NetworkRule -g $rg --rcg-name myrcg --policy-name $azfw_policy_name \
# --collection-name testnetrules --name permitany --source-addresses '*' --destination-addresses '*' \
# --ip-protocols Any --destination-ports '*' -o none
azfw_private_ip=$(az network firewall show -n $azfw_name -g $rg -o tsv --query 'ipConfigurations[0].privateIpAddress')
fi
# DNS server VM in hub to simulate onprem DNS (to test fwding from Azure DNS Resolver)
# Deploy in the hub only if not simulating onprem with S2S
if [[ "$create_onpremdns" == "yes" ]] && [[ "$create_onprem" == "no" ]]
then
echo "Creating DNS server VM..."
az vm create -n $dns_vm_name -g $rg --vnet-name $vnet_name --subnet $dns_subnet_name --public-ip-address $dns_vm_pip_name --generate-ssh-keys --image ubuntuLTS --size $vm_size -o none
dns_vm_pip=$(az network public-ip show -n $dns_vm_pip_name -g $rg --query ipAddress -o tsv)
dns_vm_nic_id=$(az vm show -n $dns_vm_name -g $rg --query 'networkProfile.networkInterfaces[0].id' -o tsv)
dns_vm_privateip=$(az network nic show --ids $dns_vm_nic_id --query 'ipConfigurations[0].privateIpAddress' -o tsv)
echo "DNS server deployed to $dns_vm_privateip, $dns_vm_pip"
echo "Installing dnsmasq"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $dns_vm_pip "sudo apt update -y && sudo apt -y install dnsmasq"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $dns_vm_pip "sudo sed -i '$ a\log-queries' /etc/dnsmasq.conf"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $dns_vm_pip "sudo systemctl restart dnsmasq"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $dns_vm_pip "sudo systemctl status dnsmasq"
echo "Adding sample DNS name $sample_fqdn with IP $sample_ip..."
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$dns_vm_pip" "sudo sed -i \"\$ a $sample_ip $sample_fqdn\" /etc/hosts"
dns_vm_nic_id=$(az vm show -n $dns_vm_name -g $rg --query 'networkProfile.networkInterfaces[0].id' -o tsv)
dns_vm_privateip=$(az network nic show --ids $dns_vm_nic_id --query 'ipConfigurations[0].privateIpAddress' -o tsv)
fi
# Client VM (hub)
echo "Creating client VM in hub VNet..."
az vm create -n $client_vm_name -g $rg --vnet-name $vnet_name --subnet $client_subnet_name --public-ip-address $client_vm_pip_name --generate-ssh-keys --image ubuntuLTS --size $vm_size -o none
client_vm_pip=$(az network public-ip show -n $client_vm_pip_name -g $rg --query ipAddress -o tsv)
client_vm_nic_id=$(az vm show -n $client_vm_name -g $rg --query 'networkProfile.networkInterfaces[0].id' -o tsv)
client_vm_privateip=$(az network nic show --ids $client_vm_nic_id --query 'ipConfigurations[0].privateIpAddress' -o tsv)
echo "Client VM deployed to $client_vm_privateip, $client_vm_pip"
# Client VM (spoke1)
if [[ "$create_spokes" == "yes" ]]
then
echo "Creating client VM in spoke1 VNet ${spoke1_vnet_name}..."
az vm create -n $spoke1_vm_name -g $rg --vnet-name $spoke1_vnet_name --subnet $spoke1_subnet_name --public-ip-address $spoke1_vm_pip_name --generate-ssh-keys --image ubuntuLTS --size $vm_size -o none
spoke1_vm_pip=$(az network public-ip show -n $spoke1_vm_pip_name -g $rg --query ipAddress -o tsv)
spoke1_vm_nic_id=$(az vm show -n $spoke1_vm_name -g $rg --query 'networkProfile.networkInterfaces[0].id' -o tsv)
spoke1_vm_privateip=$(az network nic show --ids $spoke1_vm_nic_id --query 'ipConfigurations[0].privateIpAddress' -o tsv)
echo "Client VM deployed to $spoke1_vm_privateip, $spoke1_vm_pip"
fi
# Client VM (spoke2)
if [[ "$create_spokes" == "yes" ]]
then
echo "Creating client VM in spoke2 VNet ${spoke2_vnet_name}..."
az vm create -n $spoke2_vm_name -g $rg --vnet-name $spoke2_vnet_name --subnet $spoke2_subnet_name --public-ip-address $spoke2_vm_pip_name --generate-ssh-keys --image ubuntuLTS --size $vm_size -o none
spoke2_vm_pip=$(az network public-ip show -n $spoke2_vm_pip_name -g $rg --query ipAddress -o tsv)
spoke2_vm_nic_id=$(az vm show -n $spoke2_vm_name -g $rg --query 'networkProfile.networkInterfaces[0].id' -o tsv)
spoke2_vm_privateip=$(az network nic show --ids $spoke2_vm_nic_id --query 'ipConfigurations[0].privateIpAddress' -o tsv)
echo "Client VM deployed to $spoke2_vm_privateip, $spoke2_vm_pip"
fi
# Configure DNS settings in Azure Firewall policy
if [[ "$create_azfw" == "yes" ]]
then
echo "Enabling DNS proxy in Azure Firewall policy ${azfw_policy_name}..."
# This can be either the Azure DNS Resolver's inbound endpoint IP address, or the Azure DNS IP (if the ruleset is linked to the VNet)
az network firewall policy update -n $azfw_policy_name -g $rg --enable-dns-proxy --dns-servers '168.63.129.16' -o none
# az network firewall policy update -n $azfw_policy_name -g $rg --enable-dns-proxy --dns-servers '192.168.101.4' -o none
fi
# Configure Logging in the Azure Firewall
if [[ "$create_azfw" == "yes" ]]
then
logws_name=$(az monitor log-analytics workspace list -g $rg --query '[0].name' -o tsv)
if [[ -z "$logws_name" ]]
then
echo "Creating new Log Analytics workspace"
logws_name=log$RANDOM
az monitor log-analytics workspace create -n $logws_name -g $rg -o none
else
echo "Log Analytics workspace $logws_name found"
fi
logws_id=$(az resource list -g $rg -n $logws_name --query '[].id' -o tsv)
logws_customerid=$(az monitor log-analytics workspace show -n $logws_name -g $rg --query customerId -o tsv)
azfw_id=$(az network firewall show -n $azfw_name -g $rg -o tsv --query id)
az monitor diagnostic-settings create -n mydiag --resource $azfw_id --workspace $logws_id -o none \
--metrics '[{"category": "AllMetrics", "enabled": true, "retentionPolicy": {"days": 0, "enabled": false }, "timeGrain": null}]' \
--logs '[{"category": "AzureFirewallApplicationRule", "enabled": true, "retentionPolicy": {"days": 0, "enabled": false}},
{"category": "AzureFirewallDnsProxy", "enabled": true, "retentionPolicy": {"days": 0, "enabled": false}},
{"category": "AzureFirewallNetworkRule", "enabled": true, "retentionPolicy": {"days": 0, "enabled": false}}]' >/dev/null
fi
# Associate a route table to the client VM subnet to send traffic to ifconfig.co (162.159.138.85, 162.159.137.85) through the firewall
if [[ "$create_azfw" == "yes" ]]
then
echo "Creating route table for client VM subnet..."
az network route-table create -n clientrt -l $location -g $rg -o none
az network route-table route create --route-table-name clientrt -g $rg -o none \
--address-prefix 162.159.138.85/32 -n ifconfigco1 --next-hop-type VirtualAppliance --next-hop-ip-address $azfw_private_ip
az network route-table route create --route-table-name clientrt -g $rg -o none \
--address-prefix 162.159.137.85/32 -n ifconfigco2 --next-hop-type VirtualAppliance --next-hop-ip-address $azfw_private_ip
az network vnet subnet update -g $rg --vnet-name $vnet_name -n $client_subnet_name --route-table clientrt -o none
fi
# Create DNS resolver
in_ep_subnet_id=$(az network vnet subnet show --vnet-name $vnet_name -n $resolver_in_subnet_name -g $rg --query id -o tsv)
in_ep_config="[{private-ip-address:'',private-ip-allocation-method:'Dynamic',id:'${in_ep_subnet_id}'}]"
out_ep_subnet_id=$(az network vnet subnet show --vnet-name $vnet_name -n $resolver_out_subnet_name -g $rg --query id -o tsv)
out_ep_config="[{private-ip-address:'',private-ip-allocation-method:'Dynamic',id:'${out_ep_subnet_id}'}]"
echo "Creating DNS Private Resolver..."
vnet_id=$(az network vnet show -n $vnet_name -g $rg --query id -o tsv)
az dns-resolver create -n $resolver_name --id $vnet_id -g $rg -o none
az dns-resolver inbound-endpoint create --dns-resolver-name $resolver_name --name $in_ep_name \
--ip-configurations $in_ep_config -g $rg -o none
az dns-resolver outbound-endpoint create --dns-resolver-name $resolver_name --name $out_ep_name \
--id $out_ep_subnet_id -g $rg -o none
in_ep_id=$(az dns-resolver inbound-endpoint show --dns-resolver-name $resolver_name --name $in_ep_name -g $rg --query id -o tsv)
out_ep_id=$(az dns-resolver outbound-endpoint show --dns-resolver-name $resolver_name --name $out_ep_name -g $rg --query id -o tsv)
az dns-resolver forwarding-ruleset create -n $fwd_ruleset_name -g $rg \
--outbound-endpoints "[{'id': '$out_ep_id'}]"
az dns-resolver forwarding-rule create --ruleset-name $fwd_ruleset_name -n $fwd_rule_name \
--domain-name "${sample_domain}." --forwarding-rule-state "Enabled" \
--target-dns-servers "[{ip-address:'$dns_vm_privateip',port:53}]" -g $rg -o none
spoke1_vnet_id=$(az network vnet show -n $spoke1_vnet_name -g $rg --query id -o tsv)
az dns-resolver vnet-link create --ruleset-name $fwd_ruleset_name \
--id "$spoke1_vnet_id" -g $rg --name $spoke1_vnet_name -o none
spoke2_vnet_id=$(az network vnet show -n $spoke2_vnet_name -g $rg --query id -o tsv)
az dns-resolver vnet-link create --ruleset-name $fwd_ruleset_name \
--id "$spoke2_vnet_id" -g $rg --name $spoke2_vnet_name -o none
hub_vnet_id=$(az network vnet show -n $vnet_name -g $rg --query id -o tsv)
az dns-resolver vnet-link create --ruleset-name $fwd_ruleset_name \
--id "$hub_vnet_id" -g $rg --name $vnet_name -o none
# Set the hub and spoke VNets to the inbound endpoint of the hub resolver
hub_resolver_ip=$(az dns-resolver inbound-endpoint show --dns-resolver-name $resolver_name --name $in_ep_name -g $rg --query 'ipConfigurations[0].privateIpAddress' -o tsv)
echo "Setting VNets to use the hub DNS Resolver IP $hub_resolver_ip..."
az network vnet update -n $vnet_name -g $rg --dns-servers $hub_resolver_ip -o none
if [[ "$create_spokes" == "yes" ]]
then
az network vnet update -n $spoke1_vnet_name -g $rg --dns-servers $hub_resolver_ip -o none
az network vnet update -n $spoke2_vnet_name -g $rg --dns-servers $hub_resolver_ip -o none
fi
# Refresh DNS lease VM
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$client_vm_pip" "sudo systemctl restart systemd-networkd"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$client_vm_pip" "netplan ip leases eth0 | grep DNS"
if [[ "$create_spokes" == "yes" ]]
then
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$spoke1_vm_pip" "sudo systemctl restart systemd-networkd"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$spoke1_vm_pip" "netplan ip leases eth0 | grep DNS"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$spoke2_vm_pip" "sudo systemctl restart systemd-networkd"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$spoke2_vm_pip" "netplan ip leases eth0 | grep DNS"
fi
# Simulate onprem
if [[ "$create_onprem" == "yes" ]]; then
echo "Creating VPN Gateway..."
az network vnet subnet create -g $rg -n GatewaySubnet --vnet-name $vnet_name --address-prefix $gw_subnet_prefix -o none
az network public-ip create -g $rg -n vngpip0 --sku Standard --allocation-method Static -o none
az network vnet-gateway create -g $rg --sku VpnGw1 --gateway-type Vpn \
--vpn-type RouteBased --vnet $vnet_name -n vpnvng --asn 65000 --public-ip-address vngpip0 -o none
# Function to get the first IP (default gateway) of a subnet. Example: first_ip 192.168.0.64/27
function first_ip(){
subnet=$1
IP=$(echo $subnet | cut -d/ -f 1)
IP_HEX=$(printf '%.2X%.2X%.2X%.2X\n' `echo $IP | sed -e 's/\./ /g'`)
NEXT_IP_HEX=$(printf %.8X `echo $(( 0x$IP_HEX + 1 ))`)
NEXT_IP=$(printf '%d.%d.%d.%d\n' `echo $NEXT_IP_HEX | sed -r 's/(..)/0x\1 /g'`)
echo "$NEXT_IP"
}
# Create VNet
echo "Creating onprem VNet..."
az network vnet create -n $onprem_vnet_name -g $rg --address-prefixes $onprem_vnet_prefix --subnet-name $nva_subnet_name --subnet-prefixes $nva_subnet_prefix -o none
# NSG for NVA
echo "Creating NSG ${nva_name}-nsg..."
az network nsg create -n "${nva_name}-nsg" -g $rg -o none
az network nsg rule create -n SSH --nsg-name "${nva_name}-nsg" -g $rg --priority 1000 --destination-port-ranges 22 --access Allow --protocol Tcp -o none
az network nsg rule create -n IKE --nsg-name "${nva_name}-nsg" -g $rg --priority 1010 --destination-port-ranges 4500 --access Allow --protocol Udp -o none
az network nsg rule create -n IPsec --nsg-name "${nva_name}-nsg" -g $rg --priority 1020 --destination-port-ranges 500 --access Allow --protocol Udp -o none
az network nsg rule create -n ICMP --nsg-name "${nva_name}-nsg" -g $rg --priority 1030 --destination-port-ranges '*' --access Allow --protocol Icmp -o none
# Cloudinit file for NVA
linuxnva_cloudinit_file=/tmp/linuxnva_cloudinit.txt
cat <<EOF > $linuxnva_cloudinit_file
#cloud-config
runcmd:
- apt update && apt install -y bird strongswan
- sysctl -w net.ipv4.ip_forward=1
- sysctl -w net.ipv4.conf.all.accept_redirects=0
- sysctl -w net.ipv4.conf.all.send_redirects=0
EOF
# VM for NVA
echo "Creating VM $nva_name..."
az vm create -n $nva_name -g $rg -l $location --image ubuntuLTS --generate-ssh-keys \
--public-ip-address $nva_pip_name --public-ip-sku Standard --vnet-name $onprem_vnet_name --size $nva_vm_size --subnet $nva_subnet_name \
--custom-data $linuxnva_cloudinit_file --nsg "${nva_name}-nsg" -o none
nva_nic_id=$(az vm show -n $nva_name -g "$rg" --query 'networkProfile.networkInterfaces[0].id' -o tsv)
az network nic update --ids $nva_nic_id --ip-forwarding -o none
echo "Getting information about the created VM..."
nva_pip_ip=$(az network public-ip show -n $nva_pip_name -g $rg --query ipAddress -o tsv) && echo $nva_pip_ip
nva_private_ip=$(az network nic show --ids $nva_nic_id --query 'ipConfigurations[0].privateIpAddress' -o tsv) && echo $nva_private_ip
nva_default_gw=$(first_ip "$nva_subnet_prefix") && echo $nva_default_gw
# Get VPN GW information from standalone VPN Gateway (active/active)
vpngw_bgp_asn=$(az network vnet-gateway show -n $vpngw_name -g $rg --query 'bgpSettings.asn' -o tsv) && echo $vpnwg_bgp_asn
vpngw_gw0_pip=$(az network vnet-gateway show -n $vpngw_name -g $rg --query 'bgpSettings.bgpPeeringAddresses[0].tunnelIpAddresses[0]' -o tsv) && echo $vpngw_gw0_pip
vpngw_gw0_bgp_ip=$(az network vnet-gateway show -n $vpngw_name -g $rg --query 'bgpSettings.bgpPeeringAddresses[0].defaultBgpIpAddresses[0]' -o tsv) && echo $vpngw_gw0_bgp_ip
echo "Extracted info for vpn gateway: Gateway0 $vpngw_gw0_pip, $vpngw_gw0_bgp_ip. ASN $vpngw_bgp_asn"
# VTI interfaces and static routes
# Note these changes are not reboot-persistent!!!
echo "Configuring VPN between Azure:${vpngw_gw0_pip}/${vpngw_gw0_bgp_ip} and B:${nva_pip_ip}/${nva_private_ip}..."
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $nva_pip_ip "sudo ip tunnel add vti0 local $nva_private_ip remote $vpngw_gw0_pip mode vti key 12"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $nva_pip_ip "sudo sysctl -w net.ipv4.conf.vti0.disable_policy=1"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $nva_pip_ip "sudo ip link set up dev vti0"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $nva_pip_ip "sudo ip route add ${vpngw_gw0_bgp_ip}/32 dev vti0"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $nva_pip_ip "sudo sed -i 's/# install_routes = yes/install_routes = no/' /etc/strongswan.d/charon.conf"
myip=$(curl -s4 ifconfig.co) && echo $myip
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $nva_pip_ip "sudo ip route add ${vpngw_gw0_pip}/32 via $nva_default_gw"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $nva_pip_ip "sudo ip route add ${myip}/32 via $nva_default_gw" # To not lose SSH connectivity
# IPsec config files
vpn_psk_file=/tmp/ipsec.secrets
cat <<EOF > $vpn_psk_file
$nva_pip_ip $vpngw_gw0_pip : PSK "$vpn_psk"
EOF
ipsec_file=/tmp/ipsec.conf
cat <<EOF > $ipsec_file
config setup
charondebug="all"
uniqueids=yes
strictcrlpolicy=no
conn vng0
authby=secret
leftid=$nva_pip_ip
leftsubnet=0.0.0.0/0
right= $vpngw_gw0_pip
rightsubnet=0.0.0.0/0
keyexchange=ikev2
ikelifetime=28800s
keylife=3600s
keyingtries=3
compress=no
auto=start
ike=aes256-sha1-modp1024
esp=aes256-sha1
mark=12
EOF
# Copy files to NVA and restart ipsec daemon
username=$(whoami)
scp $vpn_psk_file $nva_pip_ip:/home/$username/ipsec.secrets
scp $ipsec_file $nva_pip_ip:/home/$username/ipsec.conf
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $nva_pip_ip "sudo mv ./ipsec.* /etc/"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $nva_pip_ip "sudo systemctl restart ipsec"
# Configure BGP with Bird (NVA to VPNGW)
bird_config_file=/tmp/bird.conf
cat <<EOF > $bird_config_file
log syslog all;
router id $nva_private_ip;
protocol device {
scan time 10;
}
protocol direct {
disabled;
}
protocol kernel {
preference 254;
learn;
merge paths on;
import filter {
if net ~ ${vpngw_gw0_bgp_ip}/32 then accept;
else reject;
};
export filter {
if net ~ ${vpngw_gw0_bgp_ip}/32 then reject;
else accept;
};
}
protocol static {
import all;
# Test route
route 1.1.1.1/32 via $nva_default_gw;
route $vnet_prefix via $nva_default_gw;
}
protocol bgp vpngw0 {
description "VPN Gateway instance 0";
multihop;
local $nva_private_ip as $nva_asn;
neighbor $vpngw_gw0_bgp_ip as $vpngw_asn;
import filter {accept;};
export filter {accept;};
}
EOF
username=$(whoami)
scp $bird_config_file "${nva_pip_ip}:/home/${username}/bird.conf"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $nva_pip_ip "sudo mv /home/${username}/bird.conf /etc/bird/bird.conf"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $nva_pip_ip "sudo systemctl restart bird"
# Connect Azure to onprem
az network local-gateway create -g $rg -n onprem --gateway-ip-address $nva_pip_ip --asn $nva_asn --bgp-peering-address $nva_private_ip -o none
az network vpn-connection create -g $rg --shared-key $vpn_psk --enable-bgp -n onprem --vnet-gateway1 vpnvng --local-gateway2 onprem -l $location -o none
fi
#############################
# DNS resolution examples #
#############################
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$client_vm_pip" "nslookup $client_vm_name"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$client_vm_pip" "nslookup ${client_vm_name}.${private_dns_zone}"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$client_vm_pip" "nslookup $client_vm_privateip"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$client_vm_pip" "nslookup ${private_dns_host}.${private_dns_zone}"
###########
# Testing #
###########
# Four DNS cases supported
test_dns=azure # Can be either azure,resolver,azfw or onprem
# From hub VNet (changing the NIC settings)
# 1. Set DNS server for the client VM in the hub to either Azure, private resolver, or corp
if [[ "$test_dns" == "azure" ]]; then
echo "Setting client VM to use Azure DNS..."
az network nic update --ids $client_vm_nic_id --dns-servers '' -o none
elif [[ "$test_dns" == "resolver" ]]; then
in_ep_ip=$(az dns-resolver inbound-endpoint show --dns-resolver-name $resolver_name --name $in_ep_name -g $rg --query 'ipConfigurations[0].privateIpAddress' -o tsv)
echo "Setting client VM to use Azure DNS Resolver's inbound endpoint IP $in_ep_ip..."
az network nic update --ids $client_vm_nic_id --dns-servers $in_ep_ip -o none
elif [[ "$test_dns" == "onprem" ]]; then
if [[ "$create_onprem" == "yes" ]]; then
onprem_dns_ip=$nva_private_ip
else
onprem_dns_ip=$dns_vm_privateip
fi
echo "Setting client VM to use the corporate DNS server in $onprem_dns_ip directly..."
az network nic update --ids $client_vm_nic_id --dns-servers $onprem_dns_ip -o none
elif [[ "$test_dns" == "azfw" ]]; then
echo "Setting client VM to use the Azure Firewall in $azfw_private_ip as DNS server..."
az network nic update --ids $client_vm_nic_id --dns-servers $azfw_private_ip -o none
else
echo "Sorry, I don't recognize the test case '$test_dns'"
fi
# 2. Refresh DNS lease in hub VM
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$client_vm_pip" "sudo systemctl restart systemd-networkd"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$client_vm_pip" "netplan ip leases eth0 | grep DNS"
# 3. Test 3 names from the hub VM: an FQDN on a private DNS zone, a corp FQDN (defined in the DNS server), and a public FQDN
echo "Resolving on hub VM over a private DNS zone the FQDN '${private_dns_fqdn}'..."
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$client_vm_pip" "nslookup $private_dns_fqdn"
echo "Resolving on hub VM over a corporate DNS server the FQDN '${sample_fqdn}'..."
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$client_vm_pip" "nslookup $sample_fqdn"
echo "Resolving on hub VM public DNS name 'microsoft.com'"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$client_vm_pip" "nslookup microsoft.com"
# 4. Send traffic to ifconfig.co, which should go through the firewall and hit an FQDN-based network rule
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$client_vm_pip" "curl -s4 http://ifconfig.co" # This should not work (dropped by the FW)
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$client_vm_pip" "curl -s4 https://ifconfig.co" # This should work (allowed by the FW)
# From spoke VNets (changing the VNet settings)
for spoke_vnet_name in $spoke1_vnet_name $spoke2_vnet_name;
do
# 1. Change the spoke VNet DNS custom server config (Azure DNS or Azure Firewall)
if [[ "$test_dns" == "azure" ]]; then
echo "Setting VNet $spoke_vnet_name custom DNS servers to Azure DNS..."
az network vnet update -n $spoke_vnet_name -g $rg --dns-servers '' -o none
elif [[ "$test_dns" == "resolver" ]]; then
in_ep_ip=$(az dns-resolver inbound-endpoint show --dns-resolver-name $resolver_name --name $in_ep_name -g $rg --query 'ipConfigurations[0].privateIpAddress' -o tsv)
echo "Setting client VM to use Azure DNS Resolver's IP $in_ep_ip..."
az network nic update --ids $client_vm_nic_id --dns-servers $in_ep_ip -o none
elif [[ "$test_dns" == "onprem" ]]; then
if [[ "$create_onprem" == "yes" ]]; then
onprem_dns_ip=$nva_private_ip
else
onprem_dns_ip=$dns_vm_privateip
fi
echo "Setting VNet $spoke_vnet_name to use the corporate DNS server in $onprem_dns_ip directly..."
az network vnet update -n $spoke_vnet_name -g $rg --dns-servers $onprem_dns_ip -o none
elif [[ "$test_dns" == "azfw" ]]; then
echo "Setting VNet $spoke_vnet_name custom DNS servers to Azure Firewall..."
az network vnet update -n $spoke_vnet_name -g $rg --dns-servers $azfw_private_ip -o none
else
echo "Sorry, I don't recognize the test case '$test_dns'"
fi
# 2. Refresh DNS lease in spoke VM
if [[ "$spoke_vnet_name" == "$spoke1_vnet_name" ]]; then
spoke_vm_pip=$spoke1_vm_pip
elif [[ "$spoke_vnet_name" == "$spoke2_vnet_name" ]]; then
spoke_vm_pip=$spoke2_vm_pip
else
echo "I cannot recognize the spoke VNet name $spoke_vnet_name"
fi
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$spoke_vm_pip" "sudo systemctl restart systemd-networkd"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$spoke_vm_pip" "netplan ip leases eth0 | grep DNS"
# 3. Test 3 names from the spoke VM: an FQDN on a private DNS zone, a corp FQDN (defined in the DNS server), and a public FQDN
echo "Resolving on spoke VM over a private DNS zone the FQDN '${private_dns_fqdn}'..."
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$spoke_vm_pip" "nslookup $private_dns_fqdn"
echo "Resolving on spoke VM over a corporate DNS server the FQDN '${sample_fqdn}'..."
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$spoke_vm_pip" "nslookup $sample_fqdn"
echo "Resolving on spoke VM public DNS name 'microsoft.com'"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$spoke_vm_pip" "nslookup microsoft.com"
done
###############
# Diagnostics #
###############
# OS DNS settings
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$client_vm_pip" "netplan ip leases eth0 | grep DNS"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$spoke1_vm_pip" "netplan ip leases eth0 | grep DNS"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$spoke2_vm_pip" "netplan ip leases eth0 | grep DNS"
# NIC DNS settings
az network nic show --ids $client_vm_nic_id --query 'dnsSettings.dnsServers[0]' -o tsv
az network nic show --ids $spoke1_vm_nic_id --query 'dnsSettings.dnsServers[0]' -o tsv
az network nic show --ids $spoke2_vm_nic_id --query 'dnsSettings.dnsServers[0]' -o tsv
# VNet DNS settings
az network vnet show -n $vnet_name -g $rg --query 'dhcpOptions.dnsServers[0]' -o tsv
az network vnet show -n $spoke1_vnet_name -g $rg --query 'dhcpOptions.dnsServers[0]' -o tsv
az network vnet show -n $spoke2_vnet_name -g $rg --query 'dhcpOptions.dnsServers[0]' -o tsv
# VNet peerings
az network vnet peering list -g $rg --vnet-name $vnet_name -o table
az network vnet peering list -g $rg --vnet-name $spoke1_vnet_name -o table
az network vnet peering list -g $rg --vnet-name $spoke2_vnet_name -o table
# Az FW DNS config
az network firewall policy show -n $azfw_policy_name -g $rg --query 'dnsSettings'
# Private DNS Zone
az network private-dns zone list -g $rg -o table
az network private-dns link vnet list -g $rg -z $private_dns_zone -o table
az network private-dns record-set a list -z $private_dns_zone -g $rg --query '[].{RecordName:name,IPv4Address:aRecords[0].ipv4Address}' -o table
# DNS private resolver
az dns-resolver list -g $rg -o table
az dns-resolver inbound-endpoint list --dns-resolver-name $resolver_name -g $rg -o table
az dns-resolver inbound-endpoint list --dns-resolver-name $resolver_name -g $rg --query '[].{Name:name,Location:location,IP:ipConfigurations[0].privateIpAddress}' -o table
az dns-resolver outbound-endpoint list --dns-resolver-name $resolver_name -g $rg -o table
az dns-resolver forwarding-ruleset list -g $rg -o table
az dns-resolver forwarding-ruleset list -g $rg --query '[].{Name:name,OutboundEndpoint:dnsResolverOutboundEndpoints[0].id,Location:location}' -o table
az dns-resolver forwarding-rule list --ruleset-name $fwd_ruleset_name -g $rg -o table
az dns-resolver forwarding-rule list --ruleset-name $fwd_ruleset_name -g $rg --query '[].{Name:name,DomainName:domainName,State:forwardingRuleState,TargetDnsServer:targetDnsServers[0].ipAddress}' -o table
az dns-resolver vnet-link list --ruleset-name $fwd_ruleset_name -g $rg -o table
# Azure Firewall DNS logs
fw_net_logs_query='AzureDiagnostics
| where Category == "AzureFirewallNetworkRule"
| where TimeGenerated >= ago(5m)
| parse msg_s with Protocol " request from " SourceIP ":" SourcePortInt:int " to " TargetIP ":" TargetPortInt:int *
| parse msg_s with * ". Action: " Action1a
| parse msg_s with * " was " Action1b " to " NatDestination
| parse msg_s with Protocol2 " request from " SourceIP2 " to " TargetIP2 ". Action: " Action2
| extend SourcePort = tostring(SourcePortInt),TargetPort = tostring(TargetPortInt)
| extend Action = case(Action1a == "", case(Action1b == "",Action2,Action1b), Action1a),Protocol = case(Protocol == "", Protocol2, Protocol),SourceIP = case(SourceIP == "", SourceIP2, SourceIP),TargetIP = case(TargetIP == "", TargetIP2, TargetIP),SourcePort = case(SourcePort == "", "N/A", SourcePort),TargetPort = case(TargetPort == "", "N/A", TargetPort),NatDestination = case(NatDestination == "", "N/A", NatDestination)
//| where Action == "Deny"
//| project TimeGenerated, msg_s, Protocol, SourceIP,SourcePort,TargetIP,TargetPort,Action, NatDestination // with msg_s
| project TimeGenerated, Protocol, SourceIP,SourcePort,TargetIP,TargetPort,Action, NatDestination, Resource // without msg_s
| take 20 '
fw_dns_logs_query='AzureDiagnostics
| where Category == "AzureFirewallDnsProxy"
| parse msg_s with "DNS Request: " SourceIP ":" SourcePortInt:int " - " QueryID:int " " RequestType " " RequestClass " " hostname ". " protocol " " details
| extend
ResponseDuration = extract("[0-9]*.?[0-9]+s$", 0, msg_s),
SourcePort = tostring(SourcePortInt),
QueryID = tostring(QueryID)
| project TimeGenerated,SourceIP,hostname,RequestType,ResponseDuration,details
| where hostname contains "contoso"
| order by TimeGenerated
| take 20 '
az monitor log-analytics query -w $logws_customerid --analytics-query $fw_net_logs_query -o tsv
az monitor log-analytics query -w $logws_customerid --analytics-query $fw_dns_logs_query -o tsv
# dnsmasq logs
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $dns_vm_pip "cat /var/log/syslog | grep dnsmasq | grep contoso | tail -10"
# ######################
# # PowerShell (begin) #
# ######################
# # Variables
# $ResourceGroupName = "dns"
# $VNetName = "hub"
# $SpokeVNetName = "spoke1"
# $ResolverName = "hubresolver"
# $Location = "westeurope"
# $SubnetInName = "resolverin"
# $SubnetOutName = "resolverout"
# $EndpointInName = "inboundendpoint"
# $EndpointOutName = "outboundendpoint"
# $RulesetName = "myruleset"
# $TargetDNSIP = "192.168.53.4"
# $TargetDomain = "contoso.com."
# # Install module
# Register-PSRepository -Name LocalPSRepo -SourceLocation 'C:\Users\jomore\Downloads' -ScriptSourceLocation 'C:\Users\jomore\Downloads' -InstallationPolicy Trusted
# Install-Module Az.DnsResolver -RequiredVersion 0.1.5
# # Update-Module -Name Az.DnsResolver -RequiredVersion 0.1.5
# Get-InstalledModule -Name Az.DnsResolver
# Connect-AzAccount -Environment AzureCloud
# Select-AzSubscription -SubscriptionObject (Get-AzSubscription -SubscriptionId $SubscriptionId)
# Register-AzResourceProvider -Feature ManagedResolver -ProviderNamespace Microsoft.Network
# # Register-AzResourceProvider -ProviderNamespace Microsoft.Network
# # Create resolver in hub
# $VNet = Get-AzVirtualNetwork -Name $VNetName -ResourceGroupName $ResourceGroupName
# New-AzDnsResolver -Name $ResolverName -ResourceGroupName $ResourceGroupName -Location $Location -VirtualNetworkId $VNet.Id
# $Resolver = Get-AzDnsResolver -Name $ResolverName -ResourceGroupName $ResourceGroupName
# $Resolver.ToJsonString()
# # Configure endpoints
# $SubnetIn = Get-AzVirtualNetworkSubnetConfig -VirtualNetwork $VNet -Name $SubnetInName
# $ipConfigIn = New-AzDnsResolverIPConfigurationObject -PrivateIPAllocationMethod Dynamic -SubnetId $SubnetIn.Id
# New-AzDnsResolverInboundEndpoint -Name $EndpointInName -DnsResolverName $ResolverName -ResourceGroupName $ResourceGroupName -IPConfiguration $ipConfigIn
# $EndpointIn = Get-AzDnsResolverInboundEndpoint -Name $EndpointInName -DnsResolverName $ResolverName -ResourceGroupName $ResourceGroupName
# $EndpointIn.ToJsonString()
# $SubnetOut = Get-AzVirtualNetworkSubnetConfig -VirtualNetwork $VNet -Name $SubnetOutName
# New-AzDnsResolverOutboundEndpoint -DnsResolverName $ResolverName -Name $EndpointOutName -ResourceGroupName $ResourceGroupName -SubnetId $SubnetOut.Id
# $EndpointOut = Get-AzDnsResolverOutboundEndpoint -Name $EndpointOutName -DnsResolverName $ResolverName -ResourceGroupName $ResourceGroupName
# $EndpointOut.ToJsonString()
# # Forwarding ruleset
# New-AzDnsForwardingRuleset -Name $RulesetName -ResourceGroupName $ResourceGroupName -DnsResolverOutboundEndpoint $EndpointOut -Location $Location
# $Ruleset = Get-AzDnsForwardingRuleset -Name $RulesetName -ResourceGroupName $ResourceGroupName
# $(Get-AzDnsForwardingRuleset -Name $RulesetName -ResourceGroupName $ResourceGroupName).ToJsonString()
# # Forwarding Rule
# $TargetDNS = New-AzDnsResolverTargetDnsServerObject -IPAddress $TargetDNSIP -Port 53
# Get-AzDnsResolverTargetDnsServerObject | ft
# $ForwardingRule = New-AzDnsForwardingRulesetForwardingRule -ResourceGroupName $ResourceGroupName -DnsForwardingRulesetName $Ruleset.Name -Name "corpdomain" -DomainName $TargetDomain -ForwardingRuleState "Enabled" -TargetDnsServer @($TargetDNS)
# $(Get-AzDnsForwardingRulesetForwardingRule -ResourceGroupName $ResourceGroupName -DnsForwardingRulesetName $Ruleset.Name).ToJsonString()
# # Link to Hub VNet
# $Context = Get-AzContext
# $VnetLink = New-AzDnsForwardingRulesetVirtualNetworkLink -DnsForwardingRulesetName $Ruleset.Name -ResourceGroupName $ResourceGroupName -VirtualNetworkLinkName $VNet.Name -VirtualNetworkId $VNet.Id -SubscriptionId $Context.Subscription.Id
# Get-AzDnsForwardingRulesetVirtualNetworkLink -DnsForwardingRulesetName $Ruleset.Name -ResourceGroupName $ResourceGroupName
# # OPTIONAL: Link hub Resolver to spoke VNet
# $SpokeVNetName = "spoke1"
# $SpokeVNet = Get-AzVirtualNetwork -Name $SpokeVNetName -ResourceGroupName $ResourceGroupName
# $SpokeVnetLink = New-AzDnsForwardingRulesetVirtualNetworkLink -DnsForwardingRulesetName $Ruleset.Name -ResourceGroupName $ResourceGroupName -VirtualNetworkLinkName $SpokeVNetName -VirtualNetworkId $SpokeVNet.Id -SubscriptionId $Context.Subscription.Id
# Get-AzDnsForwardingRulesetVirtualNetworkLink -DnsForwardingRulesetName $Ruleset.Name -ResourceGroupName $ResourceGroupName
# # OPTIONAL: Create another resolver in spoke VNet
# $SpokeVNetName = "spoke1"
# $SpokeVNet = Get-AzVirtualNetwork -Name $SpokeVNetName -ResourceGroupName $ResourceGroupName
# $SpokeResolverName = $SpokeVNetName+ "resolver"
# $SpokeEndpointInName = $SpokeVNetName+ "in"
# $SpokeEndpointOutName = $SpokeVNetName+ "out"
# $SpokeRulesetName = $SpokeVNetName+ "ruleset"
# New-AzDnsResolver -Name $SpokeResolverName -ResourceGroupName $ResourceGroupName -Location $Location -VirtualNetworkId $SpokeVNet.Id
# $SpokeResolver = Get-AzDnsResolver -Name $SpokeResolverName -ResourceGroupName $ResourceGroupName
# $SpokeResolver.ToJsonString()
# $SpokeSubnetIn = Get-AzVirtualNetworkSubnetConfig -VirtualNetwork $SpokeVNet -Name $SubnetInName
# $SpokeIpConfigIn = New-AzDnsResolverIPConfigurationObject -PrivateIPAllocationMethod Dynamic -SubnetId $SpokeSubnetIn.Id
# New-AzDnsResolverInboundEndpoint -Name $SpokeEndpointInName -DnsResolverName $SpokeResolverName -ResourceGroupName $ResourceGroupName -IPConfiguration $SpokeIpConfigIn
# $SpokeEndpointIn = Get-AzDnsResolverInboundEndpoint -Name $SpokeEndpointInName -DnsResolverName $SpokeResolverName -ResourceGroupName $ResourceGroupName
# $SpokeEndpointIn.ToJsonString()
# $SpokeSubnetOut = Get-AzVirtualNetworkSubnetConfig -VirtualNetwork $SpokeVNet -Name $SubnetOutName
# New-AzDnsResolverOutboundEndpoint -DnsResolverName $SpokeResolverName -Name $SpokeEndpointOutName -ResourceGroupName $ResourceGroupName -SubnetId $SpokeSubnetOut.Id
# $SpokeEndpointOut = Get-AzDnsResolverOutboundEndpoint -Name $SpokeEndpointOutName -DnsResolverName $SpokeResolverName -ResourceGroupName $ResourceGroupName
# $SpokeEndpointOut.ToJsonString()
# New-AzDnsForwardingRuleset -Name $SpokeRulesetName -ResourceGroupName $ResourceGroupName -DnsResolverOutboundEndpoint $SpokeEndpointOut -Location $Location
# $SpokeRuleset = Get-AzDnsForwardingRuleset -Name $SpokeRulesetName -ResourceGroupName $ResourceGroupName
# $SpokeVnetLink = New-AzDnsForwardingRulesetVirtualNetworkLink -DnsForwardingRulesetName $SpokeRuleset.Name -ResourceGroupName $ResourceGroupName -VirtualNetworkLinkName $SpokeVNet.Name -VirtualNetworkId $SpokeVNet.Id -SubscriptionId $Context.Subscription.Id
# Get-AzDnsForwardingRulesetVirtualNetworkLink -DnsForwardingRulesetName $SpokeRuleset.Name -ResourceGroupName $ResourceGroupName
# # OPTIONAL: fwd rule from hub DNS Resolver to Spoke DNS Resolver for reverse DNS
# $TargetDNS = New-AzDnsResolverTargetDnsServerObject -IPAddress "10.1.1.68" -Port 53
# $TargetDomain = "1.1.10.in-addr.arpa."
# $RuleName = "spoke1"
# # Get-AzDnsResolverTargetDnsServerObject | ft
# $ForwardingRule = New-AzDnsForwardingRulesetForwardingRule -ResourceGroupName $ResourceGroupName -DnsForwardingRulesetName $SpokeRuleset.Name -Name $RuleName -DomainName $TargetDomain -ForwardingRuleState "Enabled" -TargetDnsServer @($TargetDNS)
# $(Get-AzDnsForwardingRulesetForwardingRule -ResourceGroupName $ResourceGroupName -DnsForwardingRulesetName $Ruleset.Name).ToJsonString()
# # DANGER: Delete resources
# # Hub
# Remove-AzDnsForwardingRulesetVirtualNetworkLink -DnsForwardingRulesetName $Ruleset.Name -ResourceGroupName $ResourceGroupName -VirtualNetworkLinkName $VNetName
# Remove-AzDnsForwardingRulesetVirtualNetworkLink -DnsForwardingRulesetName $Ruleset.Name -ResourceGroupName $ResourceGroupName -VirtualNetworkLinkName $SpokeVNetName
# Remove-AzDNSForwardingRuleset -ResourceGroupName $ResourceGroupName -DnsForwardingRulesetName $Ruleset.Name
# Remove-AzDnsResolverInboundEndpoint -Name $EndpointInName -DnsResolverName $ResolverName -ResourceGroupName $ResourceGroupName
# Remove-AzDnsResolverOutboundEndpoint -Name $EndpointOutName -DnsResolverName $ResolverName -ResourceGroupName $ResourceGroupName
# Remove-AzDnsResolver -Name $ResolverName -ResourceGroupName $ResourceGroupName
# # Spoke
# Remove-AzDNSForwardingRuleset -ResourceGroupName $ResourceGroupName -DnsForwardingRulesetName $SpokeRuleset.Name
# Remove-AzDnsResolverInboundEndpoint -Name $SpokeEndpointInName -DnsResolverName $SpokeResolverName -ResourceGroupName $ResourceGroupName
# Remove-AzDnsResolverOutboundEndpoint -Name $SpokeEndpointOutName -DnsResolverName $SpokeResolverName -ResourceGroupName $ResourceGroupName
# Remove-AzDnsResolver -Name $SpokeResolverName -ResourceGroupName $ResourceGroupName
####################
# PowerShell (end) #
####################