Programatically set DNS servers (Windows, MacOS) - node.js

I need to programmatically set DNS servers of the host on their active network interfaces (Wi-fi, ethernet, etc) on both Windows, MacOS and as a bonus Linux.
I want to avoid having to manually update/pollute /etc/hosts for my Kubernetes services I am running on my ingress.
Currently, my process is to manually set the DNS server for each person in my team running our app
The problem with this is that it's a manual process, and I am having trouble trying to automate it because the outputs are weirdly formatted and hard to parse. This means I am unable to know which is the proper network interface to use.
Essentially, what needs to be done is the following (on both platforms)
Get the active networks name
Set the DNS servers for the active network to 127.0.0.1 & 8.8.4.4
What is being done manually currently
MacOS:
networksetup -setdnsservers Wi-Fi 127.0.0.1 8.8.8.8
sudo killall -HUP mDNSResponder
127.0.0.1 is the local DNS server running on node that serves the A record for the service
8.8.8.8 is Google's Public DNS Server
Currently, I am assuming the user on MacOS is using the "Wi-Fi" network, but i'd like to determine this programatically
Windows
As administrator:
netsh interface show interface
Locate the network connection for which you want the DNS server changed (eg: WiFi).
netsh interface ipv4 add dns "WiFi" 127.0.0.1 index=1
netsh interface ipv4 add dns "WiFi" 8.8.8.8 index=2
ipconfig /flushdns

On macOS, I don't think this will do what you want. When you configure multiple DNS servers on macOS, the system resolver doesn't try them in order, it just fires off requests semi-randomly between the available servers. This means it'll sometimes send off requests for your private servers to the public (Google) server, get told there's no such domain, and stop there. Or it'll send requests for pubic sites to the localhost DNS, and if that doesn't respond properly decide that site doesn't work. Basically, the macOS resolver doesn't do failover.
Are your private servers under a non-standard TLD or something like that? If so, you might be able to do the job by adding a file under /etc/resolver/ to redirect queries for that TLD to the private DNS server.
Anyway, in case it is useful, here's a way to detect the primary (active) network interface and set its DNS servers in macOS:
#!/bin/bash
interfaceDevice=$(netstat -rn | awk '($1 == "default") {print $6; exit}')
if [[ -z "$interfaceDevice" ]]; then
echo "Unable to get primary network interface device" >&2
exit 1
fi
interfaceName=$(networksetup -listallhardwareports | grep -B1 "Device: $interfaceDevice\$" | sed -n 's/^Hardware Port: //p')
if [[ -z "$interfaceName" ]]; then
echo "Unable to get primary network interface name" >&2
exit 1
fi
networksetup -setdnsservers "$interfaceName" 127.0.0.1 8.8.8.8

Related

hostname -i vs hostname -I in linux

So I looked up on google about the difference between the output for hostname -i and hostname -I but couldn't get anything significant.
The output for hostname -i: 127.0.1.1
The output for hostname -I: 192.168.X.X.
All I could get was this:
-i: This option is used to get the IP(network) addresses. This option works only if the hostname is resolvable.
-I: This option is used to get all IP(network) addresses. The option doesn’t depend on the resolvability of the hostname.
It would be great if someone could elaborate on this for me.
From the information in your question I infer that your question is about linux hostname command. That's important as BSD flavor of that command (e.g. found in macOS system) has different argument set.
The man page for linux hostname command is actually very specific about the difference and you have posted already excerpt from it:
-i, --ip-address
Display the network address(es) of the host name. Note that this works only if the host name can be resolved. Avoid
using this option; use hostname --all-ip-addresses instead.
-I, --all-ip-addresses
Display all network addresses of the host. This option enumerates all configured addresses on all network interfaces.
The loopback interface and IPv6 link-local addresses are omitted. Contrary to option -i, this option does not depend
on name resolution. Do not make any assumptions about the order of the output.
The "address being resolved" (the -i argument) means that it is being resolved via DNS. You can get similar results by using some name resolution command as nslookup <yourhostname> or getent hosts <yourhostname>:
$ nslookup myhostname
Server: 127.0.0.1
Address: 127.0.0.1#53
Non-authoritative answer:
Name: myhostname
Address: X.X.X.X
The -I on the other hand iterates over all network interfaces of your host and sees how they are actually configured. That means it obtains the IP address via completely different method.
Assuming your hostname is set to myhost, hostname -i tries to resolve myhost. You probably have such a line in your /etc/hosts
127.0.0.1 myhost
This will resolve myhost as 127.0.0.1.
With hostname -I you get the addresses of your network interface(s), apparently without the loopback addresses. These addresses might be assigned by DHCP.
In your case with the output 192.168.X.X you only have one interface connected with only an IPv4 address.
My Ubuntu 19.10 system displays one IPv4 address and one IPv6 address when connected to WiFi only or two IPv4 and IPv6 addresses each when connected to both WiFi and Ethernet.

is nginx or haproxy able to do proxy stuff to google.com?

Hi my country blocked google.com anyway I have a virtual machine which is outside the country and have access to google. it has nginx & haproxy installed, based on my limited understanding these reverse proxy can do proxy to internal servers but is there anyway to let them do proxy to google.com directly?
Thanks so much.
Instead of using NGINX or HAPROXY to proxy some URL or google.com what you should do is use your VM as a proxy for the browser. Execute below on your machine
$ ssh -D 8123 -f -C -q -N sammy#example.com
Explanation of arguments
-D: Tells SSH that we want a SOCKS tunnel on the specified port number (you can choose a number between 1025-65536)
-f: Forks the process to the background
-C: Compresses the data before sending it
-q: Uses quiet mode
-N: Tells SSH that no command will be sent once the tunnel is up
This will open a socks proxy on 127.0.0.1:8123, you can set this in your browser and open google through your server.
For more detailed article refer to below
https://www.digitalocean.com/community/tutorials/how-to-route-web-traffic-securely-without-a-vpn-using-a-socks-tunnel

Check for specific string within wget result set and update the log based on that

I have a permanently VPN connection to a server in Germany. I have intermittent outages of this connection where the VPN connection drops and it falls back to default broadband ISP based internet connection path. I am trying to track this outages by using the way google works depending where your connection originating from. If I connect from my default connection in US, I get the standard google.com server, but if I connect over the VPN server in germany google.com connection attempt resolves to google.de site instead of google.com. This is a suitable criteria to see if connection is down.
So, if I issue a wget against "www.google.com" the resulting set will include either google.de in indicating that google detects that the connection is from germany or google.com which will indicate the connection is coming from U.S which means for my purposes that the VPN connection is down. I can't figure out the proper syntax for the wget and the grep to follow to make this specific determination in the script.
The script I came up with doesn't seem to work consistently. When it is executed by cru (cron) it gets US when I execute interactively I get Germany.
Any suggestions?
rm index*
wget -nv google.com 2 > /jffs/user/google.txt
cat google.txt | grep google.de
if [[ $? -eq 0 ]]; then
echo "$(date) Germany" >> /jffs/user/google.log
else
echo "$(date) U.S." >> /jffs/user/google.log
fi

Linux send URL my IP address on startup

So, I'm trying to write a simple bash script to send my internal IP address to a website of mine on startup. I am on a network with DHCP, so I don't always know what the IP address of my Raspberry Pi will be after I do a reboot over ssh. I figured I could fix this by sending my website the current IP on startup. I haven't written many bash scripts, and I'm not really sure how to send data to my website. Right now I was just trying in the terminal this:
wget -qO- http://http://mywebsite.com/private/CurrentIP.php?send=$(/sbin/ifconfig eth0|grep 'inet addr:')
But I'm not having any luck. I don't actually know much about linux, and I'm trying to learn. That's why I got the raspberry pi actually. Anyway, can someone head me in the right direction?
I already know I need to put it in /etc/init.d/.
You could do this:
IP_ADDR=$(ifconfig eth0 | sed -rn 's/^.*inet addr:(([0-9]+\.){3}[0-9]+).*$/\1/p')
wget -q -O /dev/null http://mywebsite.com/private/CurrentIP.php?send=${IP_ADDR}
...but if your machine is stuck behind NAT, $IP_ADDR won't be your externally-visible address. Might want to use $_SERVER['REMOTE_ADDR'] in your PHP instead of/in addition to this to get the address for your client that your server sees.
Edit: Sounds like you want to be able to find your Raspberry Pi on your local (DHCP-managed) network after reboots. Have you considered using Multicast DNS instead?
How it works in practice: Let's say you've set the hostname of your RasPi to gooseberry. If you've enabled a multicast DNS server on that machine, other computers on the same network segment that can send multicast DNS queries will be able to find it at the domain name gooseberry.local. This is a peer-to-peer protocol and not dependent on gooseberry receiving any specific address via DHCP - so if it reboots and receives a new address, other machines should still be able to find it.
Mac OS X has this enabled out of the box; this can be enabled on most Linux distros (on Debian/Ubuntu you'd install the avahi-daemon and libnss-mdns packages); not sure about Windows, but a quick Google shows encouraging results.
This worked for me (wget part untested, but it finds IP address):
interface="eth0"
ip_addr=$(ifconfig ${interface} | sed -rn 's/^.*inet *([0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}).*$/\1/p')
wget -q -O /dev/null http://mywebsite.com/private/CurrentIP.php?send=${ip_addr}
Can't you use:
hostname --ip-address

Change and sync hostname / ip address changes on debian linux

For changing static ip address, i set the contents of /etc/network/interfaces to
auto lo
iface lo inet loopback
allow-hotplug eth0
iface eth0 inet static
address <newaddress>
netmask <netmask>
gateway <gateway>
dns-nameservers <dns1> <dns2>
then do ifdown eth0 && ifup eth0
For changing the hostname, i do the following actions
execute hostname <newname>
set contents of /etc/hostname to <newname>
replace <oldname> with <newname> in /etc/hosts
Issues
Both ip address and host name changes don't take effect.
If I change the ip address and ping the hostname, it still resolves to the oldaddress
If I change the hostname and ping the new hostname, it cannot resolve to an ip
If I change the hostname and ping the old hostname, it is still available and resolved the current ip address.
I restart the machine and it still behaves the same way.
What am I missing?
Could the parent network play any role in this?
Also note that my machine thinks the hostname is updated after I change it.
I think this is not actually a problem and this behavior is explained by arp caching.
The ARP tool manipulates or displays the kernel's IPv4 network neighbour and this includes in some way your host as well.
The arp command has many switches you can work on as, for example, the following command:
arp -n
This command prints out the list of arp cache entries.
Unfortunately there is no command to flush it hence, you have 2 options.
Option 1: You wait for the cache to update (won't take long)
Option 2: You run the following very basic script and you see:
#!/bin/sh
for i in `awk -F ' ' '{ if ( $1 ~ /[0-9{1,3}].[0-9{1,3}].[0-9{1,3}].[0-9{1,3}]/ ) print $1 }' /proc/net/arp` ;
do
arp -d $i
done
The script is not mine, I have reported the only I usually run which was taken originally from this well done example:
http://www.lainoox.com/display-add-flush-arpcache-linux-arp/
I hope this helps in some way.
Changing /etc/hostname will have the affect of changing the hostname displayed on your terminal, welcome messages, in your logs and anywhere else the system uses hostname. These are all vanity changes.
Channging /etc/hosts will change your local host-name resolution (i.e. translating an ip address to a hostname and vise versa) Anything DNS does not resolv or anything you want to override locally. By default, the local files override network resolution. This is determined in /etc/nsswitch which says to use local files first then then dns for host resolution.
The important thing to keep in mind here is that these changes will not affect how othesr on a network would determine this host's ip address or name, which of course is handled through DNS or maybe their local /etc/hosts file(s).
yeah resolv.conf is for dns. as is which handles NAMES and anything that has to do with the internet. Such as ping. dns resolvc locally weather you have server or not thus the hostname / ect hosts which ALSO handle dns. your resolv.conf will update from your isp when you connect or you can change it by hand / set some thing more dynamic on a bridged interface

Resources