There is, for what it's worth, very little reason why the best scanner need be written in C. Scanners aren't even I/O bound in their most common use case; they're timer-bound.
There is, for what it's worth, very little reason why the best scanner need be written in C. Scanners aren't even I/O bound in their most common use case; they're timer-bound.
If you want a better one written in something else, then get cracking...
[1] Yeah, I know it was mostly hacked together using Bash and Perl, but that was a long time ago. Now it's mostly C. I'm suspecting they rewrote the performance-critical stuff in C, and left everything else alone. Not sure, though; I don't follow Git development.
Rather I just intensely dislike when people pick language choice to focus on. You pick your language based on what your team knows, and if you can ship with it. Picking it for any other reason just makes you come off in a PHB type of way. If you have real criticisms and suggestions to make, then do so and make the world a better place in the process.
This isn't a controversial statement. Nobody thinks nmap is the fastest possible scanner. To argue that n+1map should be written in C, you have to make a case for what aspect of a port scanner benefits from C. Which is why I pointed out: nmap doesn't even look I/O bound; it looks timer-bound. And in most cases, neither I/O-bound nor timer-bound programs benefit greatly from locality, cheaper copies, or (within reason) optimized memory allocation and layout.
* When performance matters and can be gained through writing C code --- for instance, if you're compute-bound, or if you need fast access to data structures.
* When building incremental improvements to large C codebases --- ie, writing a loadable kernel module.
* When you're deploying in small-footprint environments.
What are the other cases where C makes sense?
I brought up the C thing not because I want to take potshots at what is probably my favorite language, but because a majority of the developers on HN don't write C, and you'd hate for them not to take a crack at competing with nmap because they had a faulty belief that they'd need to use C.
C was and is a good choice. I'd be a lot more surprised if it was written in Java or Perl.
I don't know what the best alternatives would be and while I doubt I can contribute much to the discussion, I've read your other posts on security with interest and would be interested to hear which language you'd pick and why.
Virtually any language will work for this (which is why you should avoid C). About the only thing I'd steer you clear of is a JVM language. The JVM is ordinarily a win, but here, where you want the path-of-least-resistance to getting pcap into your program, it's a bit of a pain. So scratch Scala from the list. Other than that, have fun.
But use Lisp. It's a great first Lisp project.
Someone else should write the best possible port scanner and free nmap up to be the giant network profiling system it clearly wants to be.
What exactly does that mean? Nmap certainly isn't constrained to the UX of a port scanner. In fact, their expansion wasn't even in the form of bundled build, you can get all the tools separated, like: nmap, nping, ncat, ncrack...
So actually, it really isn't detracting from its basic purpose, you can still run simple network scans. But, if you got the knowledge, skills and the other tools installed, you can then also do much than advanced network scans, like vulnerability discovery and exploitation, passwords bruteforcing, etc...
Your comment isn't making much sense to me, please help me understand.
Oh, and it takes _for_ _ever_ to run. I'll pastie the 50 line EventMachine scripts I race it with when people on my team get stuck waiting for 12-hour nmap runs.
class HostProbe
module Probe
attr_accessor :bp
def connection_completed
@win = true
end
def unbind
self.bp.closed(self, @win)
end
end
def closed(obj, won)
@inflight_now -= 1
port = @inflight_q.delete(obj)
if won
puts "%TARGET-LISTENING: #{ @target }:#{ port }"
end
fill()
end
def sweep
Generator.new do |g|
(1..65535).each {|port| g.yield port}
end
end
def fill
@inflight_now.upto(@inflight_max) {
@inflight_now += 1
if(port = @sweep.next)
EventMachine::connect(@target, port, Probe) do |c|
c.bp = self
@inflight_q[c] = port
end
end
}
end
def initialize(host, opts={})
@target = host
@sweep = sweep
@inflight_q = {}
@inflight_now = 0
@inflight_max = opts[:inflight_max] || 10
fill()
end
end
EventMachine::run {
HostProbe.new(ARGV[0])
}
I think that may be it? I'm not even going to bother seeing if it evaluates. I write that stupid script once a month or so. There is probably a set of nmap options that crushes it for speed, but with the default options and a firewalled target network (ie: most professional nmap targets), I lap nmap with it.Best Possible Port Scanner... BEST... sorry, it doesn't fit. We could give you say the Best Egregious Scanning Tool, would that work?
What about all the packet manipulation code? Bit twiddling tends to be difficult in other languages.