Getting domain host name in ruby - ruby

Is there a possible way to get the domain's hostname in ruby?
For example:
$ host api.heroku.com
api.heroku.com is an alias for api-default.herokussl.com.
api-default.herokussl.com is an alias for elb027033-298234319.us-east-1.elb.amazonaws.com.
elb027033-298234319.us-east-1.elb.amazonaws.com has address 23.23.76.65
elb027033-298234319.us-east-1.elb.amazonaws.com has address 23.21.240.208
elb027033-298234319.us-east-1.elb.amazonaws.com has address 107.22.242.236
host would be the best example, because it'll also show if the domain/subdomain is pointing to another host like amazonAWS or etc.

not as useful as executing host domain.com command from ruby
I beg to differ... (but it does involve knowing what data you want, and how DNS works).
require 'resolv'
def host(address)
Resolv::DNS.open do |dns|
loop do
ress = dns.getresources address, Resolv::DNS::Resource::IN::CNAME
break if ress.empty?
canonical_name = ress.first.name.to_s
puts "#{address} is an alias for #{canonical_name}"
address = canonical_name
end
ress = dns.getresources address, Resolv::DNS::Resource::IN::A
addresses = ress.each do |r|
puts "#{address} has address #{r.address.to_s}"
end
end
return
end
host("api.heroku.com")

Related

how do I convert int32 IP address into octets in ruby?

I'm looking for the opposite to this:
require 'ipaddr'
ip = IPAddr.new "10.0.2.15"
ip.to_i # 167772687
I need to pass something like 167772687, and want to get back "10.0.2.15".
This:
ip = IPAddr.new 167772687
returns the error:
IPAddr::AddressFamilyError: address family must be specified
How to I specify that I'm passing int32?
OK, found the answer:
require 'ipaddr'
ip = IPAddr.new(167772687, family = Socket::AF_INET)
ip.to_s # "10.0.2.15"

search to return list of nodes ip in specific format in chef

I need to do a search in a chef recipe that returns the IP's of all nodes in this specific format
'IP','IP',etc
so far by searching I've come up with this but the output is not exactly in the format that I want and I don't know how to change it.
ip = Array.new
search(:node, "name:chef-node*") do |n|
n["network"]["interfaces"]["eth1"]["addresses"].each_pair do |address,value|
ip << address if value.has_key?("broadcast")
end if n["network"]["interfaces"]["eth1"]
end
the output is like this:
["10.22.33.33", "10.22.33.38", "10.21.33.24"]
and I need it like this:
'10.210.39.231','10.209.161.18','10.210.66.240'
How would I achieve that?
ip = ["10.22.33.33", "10.22.33.38", "10.21.33.24"]
ip.map { |x| "'#{x}'" }.join(',')
# => "'10.22.33.33','10.22.33.38','10.21.33.24'"
You have a nice Array or IPs. Just use method join over it.
ip = ["10.22.33.33", "10.22.33.38", "10.21.33.24"]
ip.join(",")

How to get IP of Heroku server, where is placed my app?

I am trying to get IP address of server, where is running my app. In PHP exists the function called GetHostByName() (or something like that), what is the alternative for Ruby?
You can use this (no shell required):
require 'socket'
def local_ip
orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true # turn off reverse DNS resolution temporarily
UDPSocket.open do |s|
s.connect '64.233.187.99', 1
s.addr.last
end
ensure
Socket.do_not_reverse_lookup = orig
end
Output:
# irb:0> local_ip
# => "192.168.0.1"
I use this function, but credit goes to: http://coderrr.wordpress.com/2008/05/28/get-your-local-ip-address/

Ruby: get local IP (nix)

I need to get my IP (that is DHCP). I use this in my environment.rb:
LOCAL_IP = `ifconfig wlan0`.match(/inet addr:(\d*\.\d*\.\d*\.\d*)/)[1] || "localhost"
But is there rubyway or more clean solution?
A server typically has more than one interface, at least one private and one public.
Since all the answers here deal with this simple scenario, a cleaner way is to ask Socket for the current ip_address_list() as in:
require 'socket'
def my_first_private_ipv4
Socket.ip_address_list.detect{|intf| intf.ipv4_private?}
end
def my_first_public_ipv4
Socket.ip_address_list.detect{|intf| intf.ipv4? and !intf.ipv4_loopback? and !intf.ipv4_multicast? and !intf.ipv4_private?}
end
Both returns an Addrinfo object, so if you need a string you can use the ip_address() method, as in:
ip= my_first_public_ipv4.ip_address unless my_first_public_ipv4.nil?
You can easily work out the more suitable solution to your case changing Addrinfo methods used to filter the required interface address.
require 'socket'
def local_ip
orig = Socket.do_not_reverse_lookup
Socket.do_not_reverse_lookup =true # turn off reverse DNS resolution temporarily
UDPSocket.open do |s|
s.connect '64.233.187.99', 1 #google
s.addr.last
end
ensure
Socket.do_not_reverse_lookup = orig
end
puts local_ip
Found here.
Here is a small modification of steenslag's solution
require "socket"
local_ip = UDPSocket.open {|s| s.connect("64.233.187.99", 1); s.addr.last}

Reverse DNS in Ruby?

I'm in an environment with a lot of computers that haven't been
properly inventoried. Basically, no one knows which IP goes with which
mac address and which hostname. So I wrote the following:
# This script goes down the entire IP range and attempts to
# retrieve the Hostname and mac address and outputs them
# into a file. Yay!
require "socket"
TwoOctets = "10.26"
def computer_exists?(computerip)
system("ping -c 1 -W 1 #{computerip}")
end
def append_to_file(line)
file = File.open("output.txt", "a")
file.puts(line)
file.close
end
def getInfo(current_ip)
begin
if computer_exists?(current_ip)
arp_output = `arp -v #{current_ip}`
mac_addr = arp_output.to_s.match(/..:..:..:..:..:../)
host_name = Socket.gethostbyname(current_ip)
append_to_file("#{host_name[0]} - #{current_ip} - #{mac_addr}\n")
end
rescue SocketError => mySocketError
append_to_file("unknown - #{current_ip} - #{mac_addr}")
end
end
(6..8).each do |i|
case i
when 6
for j in (1..190)
current_ip = "#{TwoOctets}.#{i}.#{j}"
getInfo(current_ip)
end
when 7
for j in (1..255)
current_ip = "#{TwoOctets}.#{i}.#{j}"
getInfo(current_ip)
end
when 8
for j in (1..52)
current_ip = "#{TwoOctets}.#{i}.#{j}"
getInfo(current_ip)
end
end
end
Everything works except it does not find a Reverse DNS.
Sample output that I'm getting is this:
10.26.6.12 - 10.26.6.12 - 00:11:11:9B:13:9F
10.26.6.17 - 10.26.6.17 - 08:00:69:9A:97:C3
10.26.6.18 - 10.26.6.18 - 08:00:69:93:2C:E2
If I do nslookup 10.26.6.12 then I get the correct reverse DNS so
that shows that my machine is seeing the DNS server.
I have tried Socket.gethostbyname, gethostbyaddr, but it doesn't work.
Any guidance will be much appreciated.
Today I also needed reverse DNS lookup and I've found very simple standard solution:
require 'resolv'
host_name = Resolv.getname(ip_address_here)
It seems it uses timeout which helps in rough cases.
I would check out getaddrinfo. If you replace the line:
host_name = Socket.gethostbyname(current_ip)
with:
host_name = Socket.getaddrinfo(current_ip, 0, Socket::AF_UNSPEC, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME)[0][1]
The getaddrinfo function returns an array of arrays. You can read more about it at:
Ruby Socket Docs
This also works:
host_name = Socket.getaddrinfo(current_ip,nil)
append_to_file("#{host_name[0][2]} - #{current_ip} - #{mac_addr}\n")
I'm not sure why gethostbyaddr didn't also work.

Resources