Is there a standard tool similar to DNS, but for mapping names to hostname/port number combos? - dns

I have a number of services running on various machines which need to communicate over arbitrary ports. Right now port discovery happens by pushing a config file to each machine which contains mappings of a service-name to a hostname/port combo.
For all the same reasons that DNS works better than manually maintaining an /etc/hosts on each machine, I'd like to have a centralized system to register and lookup these hostname/port combos.
Yes, building a simple version of this system wouldn't take long at all (it's just a key-value store), but ideally the service would be fast, redundant, auto-updating and have fail-over, which would obviously take a bit more time to build from scratch.
I can't imagine I'm the first to need such a tool, but so far my Google-fu has failed me. Is there something out there built for this purpose? Or should I just set up Kyoto Tycoon or ZooKeeper and write a bit of caching/lookup/failover logic myself?

DNS supports SRV records that are designed just for this (service location.)
SRV records are of the following form (courtesy Wikipedia):
_service._proto.name TTL class SRV priority weight port target
service: the symbolic name of the desired service.
proto: the transport protocol of the desired service; this is usually either TCP or UDP.
name: the domain name for which this record is valid.
TTL: standard DNS time to live field.
class: standard DNS class field (this is always IN).
priority: the priority of the target host, lower value means more preferred.
weight: A relative weight for records with the same priority.
port: the TCP or UDP port on which the service is to be found.
target: the canonical hostname of the machine providing the service.
Most modern DNS servers support SRV records.

Avahi advertises services (by port) that each machine offers. (aka Apple's Bonjour)
Not sure if it's exactly what you're looking for, but definately in this vein.
The concept is that each machine would announce what services it is running on each port.
But this is limited to a LAN implementation, which I'm not sure fits your requirements.
To add a little more meat to this answer, here is an example service file for Avahi advertising a webpage:
<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name replace-wildcards="yes">%h Web Server</name>
<service>
<type>_http._tcp</type>
<port>80</port>
</service>
</service-group>

I personally think zookeeper is a great fit for this use case. Ephemeral nodes mean that registration cleanup is not a problem, freeing you to use dynamic port allocation on the server side and watches will help with rebalancing client->server mappings. That said, using zookeeper for server side registration and using DNS SRV records for client side lookup(using a zookeeper to dns bridge) would work well for most use cases.

Related

Nginx: pair nginx-balancer

At the moment there is a nginx-balancer (Centos 7, a virtual machine with a white address) proxying to a large number of backend Apache servers. It is necessary to implement a failover cluster of two balancers on nginx. Fault tolerance is trially implemented using a virtual ip address (keepalived is used). Tell me what you can read about the pair nginx-balancer or how it can be implemented: all requests coming to them on the same virtual ip-address are evenly distributed between the two of them, but if one of them fails, the remaining one takes everything on itself?
At the moment, it turns out that there are two identical balancers and the benefit of the second is only in insurance. In the moments of full work of the main (master), the second (backup) is uselessly idle.
What you are describing is active-active HA.. you can find something on google for nginx+ but by briefly looking at it I don't really see it as true active/active = there is not just one virtual (floating) IP.. instead active/active is achieved by using two floating IPs (two VRRP groups - one VIP address active on each nginx) and then using round-robin DNS A record containing both addresses.
As far as I know keepalived is using VRRP protocol which in some implementations can provide 'true' active/active.. anyway I'm not sure keepalived supports this. Based on informatin I'm able to lookup it's not possible.

Load balancer on Bind level with websocket support?

I am trying to finally solve the problem of the best, most effective, possibly low-cost way to scale a huge NodeJS/MongoDB, real-time, modern app, using Nginx. I do not have such app, it is strictly theoretical: I think it is good to learn and to do it the correct way since the very beginning, so it is easy to scale in case of growing in a future.
Below is a schema of my "contemplations" of what I managed to figure out. I was trying to take into account the most important aspects of such infrastructure, yet not including the application itself (optimizating mongoDB queries etc.). I assume the application is universal, so it might fit Facebook-like-social-network or IMDB-like-app as well.
The idea is, all You have to do - in order to effective scale - is to simply add more servers of a proper type. The schema goes like this (for a high res img, click here):
My question is, how to add few more (P)roxy servers, so in case of being offline, this machine has some working substitutes? In other words, is it possible to add some few more records A in Bind, and make it somehow supporting websockets, the similar way Nginx IP_HASH directive within upstream section does? It would be perfect to use a load balancer (supporting Websockets) on Bind level to enhance all the app.
Bind9 uses round-rubin to serve proper A record (if many), but it is defined to be ciclic.
;; A records section
proxy1 IN A 192.168.1.1
proxy2 IN A 192.168.1.2
proxy3 IN A 192.168.1.3
proxy4 IN A 192.168.1.4
How to handle websockets with many A records servers (using nginx as a proxy servers)?
Cheers!
Mike

Discovering a machines default DNS

I'm writing a small DNS proxy. It listens for incoming UDP messages on a port and resolves them using a specified DNS (e.g. google's DNS 8.8.8.8) and sends the response back to the client.
I would like to be able to detect the default DNS a machines uses. Every OS has an option to obtain the DNS server address automatically. I was wondering how this is done. Is there a protocol on top of UDP or TCP, or something else entirely?
I'm using C#, but the language isn't important.
Finding which DNS the current computer uses as default is highly dependent on both which OS you use and which language you use. If you use Java or .NET, or another platform independent language you might not need to worry about the OS bit though.
Client computers usually "auto-discover" which DNS to use in the DHCP response from the DHCP server. That is when they receive their IP address they also get which DNS server to use. They might also get addresses to WINS servers and a multitude of custom options.
You can find the DNS server by typing ipconfig/all in coand prompt. This will gove you the address of your DNS server.

How to select a static port number for a custom app?

We've got a custom application that needs to serve requests on it's own port number. We really don't care what the number is, although we'll stick to that port after we decide. How do I select a number which is least likely to conflict with other applications or services that are running on the user's system?
Are there any rules or standards we should follow?
A clarification: once we pick a port, we need to stick with it. Can't use a dynamic one. We're building a custom SFTP server and we'll have to tell our customers what port it's running on.
For a static application, consider checking /etc/services to find a port that will not collide with anything else you are using and isn't in common use elsewhere.
$ tail /etc/services
nimspooler 48001/udp # Nimbus Spooler
nimhub 48002/tcp # Nimbus Hub
nimhub 48002/udp # Nimbus Hub
nimgtw 48003/tcp # Nimbus Gateway
nimgtw 48003/udp # Nimbus Gateway
com-bardac-dw 48556/tcp # com-bardac-dw
com-bardac-dw 48556/udp # com-bardac-dw
iqobject 48619/tcp # iqobject
iqobject 48619/udp # iqobject
If you can't predict the exact kind of environment your application is going to run, just don't bother with this. Pick any number over 1024 and also make it configurable so the user can change it in case of conflict with another service/application.
Of course you can still avoid very common ports like 8080 (alternative HTTP) or 3128 (proxies like squid), 1666 (perforce), etc. You can check a comprehensive list of known ports here, or take a look at /etc/services.
If you don't care about the port number, and don't mind that it changes every time your program is run, simply don't bind the port before you listen on it (or bind with port 0, if you want to bind a specific IP address). In both cases, you're telling the OS to pick a free port for you.
After you begin listening, use getsockname to find out which port was picked. You can write it to a file, display on it on the screen, have a child inherit it via fork, etc.
If you want a unique port number for your application, you need to request an assignment from IANA, who maintain the Service Name and Transport Protocol Port Number Registry for the IETF. /etc/services and other secondary records are populated from the IANA registry.
Please do not simply pick a number and ship your application (as mentioned in another answer), because sooner or later, IANA will assign the port you're squatting on to an incoming request, which can lead to conflicts for your application and the unaware assignee.

Can the DNS Server have source IP?

Short Question :
Since DNS is anycast, is there any way for a DNS Server to know the "first" source DNS Query originated from?
Long Question :
I've developed a custom DynDNS server using PowerDNS, I want to feed it information via web interface by users. I want the web interface to update records for each user "based on IP".
So when the DNS Server gets requests, If it could determine the source IP, it'd be easy to return records associated with that IP.
As long as I tested, the DNS Server can only know the "last" node IP on the DNS chain, not the source. Is there any way?
Regards
Google and Yahoo! submitted a draft (draft-vandergaast-edns-client-ip-01) to the IETF DNS Extensions Working Group that proposed a new EDNS0 option within DNS requests that recursive servers could use to indicate their own client's IP address to the upstream authoritative server.
The intent was to theoretically optimise the use of Content Delivery Networks by ensuring that the web server addresses returned were based on the end user's IP address, rather than on the address of the end user's DNS server.
The idea was not well received and wasn't accepted by the working group because it intentionally broke the caching layer of the DNS, and the draft has subsequently expired.
UPDATE - a variation on this has subsequently been published as RFC 7871.
Perhaps you have control of the software performing the lookup? If so, you could include the IP address as part of the request, e.g.
23-34-45-56.www.example.com
to which your custom-written server replies
23-34-45-56.www.example.com 1800 CNAME www-europe.example.com
or
23-34-45-56.www.example.com 300 A 34.45.56.67
etc.
If the client is a web browser, complications arise due to NAT, HTTP proxies, and the inability to query host interface addresses directly from Javascript. However, you might be able to do an AJAX-style lookup to a what's-my-ip service, which understands X-Forwarded-For.
Long answer to Short Question :
DNS is not anycast. Some content DNS server owners use anycasting to distribute servers in multiple physical locations around the world, but the DNS/UDP and DNS/TCP protocols themselves are not anycast. The notion simply doesn't exist at that protocol layer.
Short answer to Long Question :
No.
Expansion
As noted, there's nothing in the DNS protocol for this. Moreover, the relationship between front-end and back-end transactions at a caching resolving proxy DNS server is not one-to-one.
You'll have to use whatever client differentiation mechanisms exist in the actual service protocol that you're using, instead of putting your client differentiation in the name→IP address lookup mechanism. Client differentiation for other services doesn't belong in name→IP address lookup, anyway. Such lookup is common to multiple protocols, for starters. Use the mechanisms of whatever actual service protocol is being used by the clients who are communicating with your servers.

Resources