Created
November 7, 2012 09:49
-
-
Save sivagao/4030471 to your computer and use it in GitHub Desktop.
using Timeout, TCPServer, socket, net,ssh, pcaplet(packet analysis)/http#practical ruby for system administrator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "socket" | |
socket = TCPSocket.open("www.theonion.com", "80") | |
TCPSocket.open("www.theonion.com", 80) do |socket| | |
socket.puts "GET / HTTP/1.0\n\n" | |
puts socket.read | |
end | |
attempts = 0 | |
begin | |
attempts += 1 | |
TCPSocket.open("www.example.com", 80) { |socket| ... } | |
rescue | |
if attempts < 3 then sleep 5 and retry | |
else puts "I've had enough of this" | |
end | |
end | |
require "timeout" | |
begin | |
Timeout::timeout(5) do | |
TCPSocket.open("www.example.com", 80) { |socket| ... } | |
end | |
rescue | |
puts "something untoward happened - how bothersome" | |
end | |
#timeout.rb | |
module Timeout | |
class Error< Interrupt | |
end | |
def timeout(sec, exception=Error) | |
return yield if sec == nil or sec.zero? | |
begin | |
x = Thread.current | |
y = Thread.start { | |
sleep sec | |
x.raise exception, "execution expired" if x.alive? | |
} | |
yield sec | |
# line omitted as irrelevant | |
ensure | |
y.kill if y and y.alive? | |
end | |
end | |
module_function :timeout | |
end | |
require "timeout" | |
class TCPSocket | |
def self.can_connect?(ip, port, wait_secs = 5) | |
Timeout::timeout(wait_secs) { open(ip, port) } | |
return true | |
rescue | |
return false | |
end | |
class DNSRecord | |
def value | |
return @ips.first unless @type == "A" and @ips.size > 1 | |
@ips.find { |ip| TCPSocket.can_connect?(ip, 80) } || @ips.first | |
end | |
end | |
require "net/http" | |
Net::HTTP.new("slashdot.org").get("/").each_header do |key, value| | |
next if key == "x-powered-by" or not key =~ /x-(.*)/ | |
puts "#{$1.capitalize} says #{value.inspect}" | |
break | |
end | |
require "cgi" | |
require "net/http" | |
class WebSession | |
def initialize(url, port = 80) | |
@session = Net::HTTP.new(host, port) | |
@cookies = {} | |
end | |
def get(path) | |
response = @session.get(path, retrieve_cookies(path)) | |
collect_cookies(response) | |
return response.body | |
end | |
def post(path, pairs) | |
header = retrieve_cookies(path) | |
header["content-type"] = "application/x-www-form-urlencoded" | |
data = pairs.map { |k, v| "#{k}=#{CGI.escape(v.to_s)}") }.join("&") | |
response = @session.post(path, data, header) | |
collect_cookies(response) | |
return response.body | |
end | |
private | |
def collect_cookies(response) | |
cookie = response["set-cookie"] | |
return unless cookie | |
fields, cookie_path = {}, nil | |
cookie.split(";").each do |f| | |
raise "Unable to parse cookie from #{path.inspect}" unless➥ | |
f =~ /^(.*?)=(.*?)$/ | |
if $1 == "path" then cookie_path = $2 | |
else fields[$1] = $2 | |
end | |
end | |
raise "Unable to parse cookie [no path]: #{cookie.inspect}" unless cookie_path | |
@cookies[cookie_path] = fields | |
end | |
def retrieve_cookies(path) | |
cookies = @cookies[path] || @cookies["/"] | |
return {} unless cookies | |
return {"cookie" => cookies.map { |k, v| "#{k}=#{v}" }.join(";")} | |
end | |
end | |
class MegaFishCannon < WebSession | |
def initialize(url, uname, pass) | |
super(url, 5000) | |
post("/", "login" => uname, "password" => pass) | |
end | |
# Listing 8-9. Methods to Affect State Changes of the Cannon | |
def load_fish(name) | |
post("/loadfish.cgi", "name" => name) | |
end | |
def point_cannon(degrees, metres) | |
post("/movebarrel.cgi", "degrees" => degrees, "metres" => metres) | |
end | |
def fire | |
post("/fire.cgi") | |
end | |
end | |
require "socket" | |
server = TCPServer.new(34891) | |
while (session = server.accept) | |
command = session.readline.chomp | |
if command =~ /^([\d\.]+) ([\+-\/\*]) ([\d\.]+)$/ | |
x, y = $1.to_f, $3.to_f | |
result = case $2 | |
when "+" then x + y | |
when "-" then x - y | |
when "*" then x * y | |
when "/" then y == 0 ? "inf" : x / y | |
end | |
session.puts "= #{result}" | |
end | |
session.close | |
end | |
# select based to support multi client to connect | |
require "socket" | |
server = TCPServer.new(34891) | |
sockets = [server] | |
loop do | |
read_ready, write_ready, error_ready = IO.select(sockets) | |
read_ready.each do |socket| | |
if socket == server then sockets << server.accept | |
else | |
command = socket.readline.chomp | |
if command =~ /^([\d\.]+) ([\+-\/\*]) ([\d\.]+)$/ | |
# etc... | |
end | |
socket.close | |
sockets.delete(socket) | |
end | |
end | |
end | |
# Listing 8-16. A Simple Arithmetic Server (Thread Based) | |
require "socket" | |
server = TCPServer.new(34891) | |
while (session = server.accept) | |
Thread.new(session) do |s| | |
command = s.readline.chomp | |
if command =~ /^([\d\.]+) ([\+-\/\*]) ([\d\.]+)$/ | |
x, y = $1.to_f, $3.to_f | |
result = case $2 | |
when "+" then x + y | |
when "-" then x - y | |
when "*" then x * y | |
when "/" then y == 0 ? "inf" : x / y | |
end | |
s.puts "= #{result}" | |
end | |
s.close | |
end | |
end | |
require "net/ssh" | |
Net::SSH.start(url, user, pass) do |ssh| | |
shell = ssh.shell.sync | |
puts shell.ruby("-v").stdout | |
end | |
require "net/ssh" | |
class RemoteHost | |
def initialize(url, user = root) | |
@shell = Net::SSH.start(url, user).shell.sync | |
end | |
def clear_dirs(*dirs) | |
dirs.each { |dir| @shell.send_command("rm -rf #{dir}/*") } | |
end | |
end | |
unsafe_hosts.each do |host| | |
RemoteHost.new(host).clear_dirs("/tmp", "/opt") | |
end | |
# install pcap , the packet analysis tool | |
$ tar -xzf ruby-pcap-0.6.tar.gz | |
$ cd pcap | |
$ ruby extconf.rb | |
$ make | |
$ make install | |
# Definition of a BWHost Class For Tracking BandWidth Usage | |
require "pcaplet" | |
sniffer = Pcap::Pcaplet.new | |
sniffer.each_packet { |pkt| p pkt } | |
sniffer.close | |
class BWHost | |
attr_reader :ip | |
def initialize(ip) | |
@ip = ip | |
@received, @sent = [], [] | |
end | |
def received(bytes, from, at = Time.now) | |
@received << [bytes, from, at] | |
end | |
def sent(bytes, to, at = Time.now) | |
@sent << [bytes, from, at] | |
end | |
def total_received(options = {}) | |
total(@received, options[:earliest], options[:latest]) | |
end | |
def total_sent(options = {}) | |
total(@sent, options[:earliest], options[:latest]) | |
end | |
private | |
def total(events, earliest, latest) | |
events.inject(0) do |sum, event| | |
if ((earliest and event[2] >= earliest) or not earliest) and | |
((latest and event[2] <= latest) or not latest) | |
sum + event | |
else sum | |
end | |
end | |
end | |
end | |
# - Listing 8-21. Bandwidth-Monitoring Script | |
require "pcaplet" | |
hosts = {} | |
sniffer = Pcap::Pcaplet.new | |
sniffer.each_packet do |pkt| | |
next unless pkt.ip? | |
src, dst, = pkt.ip_src, pkt.ip_dst | |
size, time = pkt.size, pkt.time | |
(hosts[src] ||= BWHost.new(src)).sent(size, dst, time) | |
(hosts[dst] ||= BWHost.new(dst)).received(size, src, time) | |
end | |
sniffer.close | |
hosts.each do |ip, data| | |
puts "#{ip} sent #{data.total_sent}B and received #{data.total_received}B" | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment