Add NETFILTER_NFLOG (ULOG) support
This commit is contained in:
14
examples/nflog.rb
Normal file
14
examples/nflog.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
LIBDIR = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
||||
$LOAD_PATH.unshift LIBDIR
|
||||
|
||||
require 'pp'
|
||||
require 'netlink/nflog'
|
||||
|
||||
# Example of using Netlink::NFLog to capture all outbound packets
|
||||
# to TCP port 7551. Use "telnet 127.0.0.1 7551" to test.
|
||||
|
||||
#system("iptables -I OUTPUT -j ULOG --ulog-nlgroup 1 -p tcp --destination-port 7551")
|
||||
nl = Netlink::NFLog::Socket.new(:group => 1)
|
||||
nl.dequeue_packets do |pkt|
|
||||
p pkt
|
||||
end
|
@@ -101,6 +101,11 @@ class CStruct
|
||||
end
|
||||
end
|
||||
|
||||
# This hook is called after unpacking from binary, and can be used
|
||||
# for fixing up the data
|
||||
def after_parse
|
||||
end
|
||||
|
||||
def to_hash
|
||||
@attrs
|
||||
end
|
||||
@@ -177,6 +182,7 @@ class CStruct
|
||||
data.unpack(self::FORMAT).zip(self::FIELDS).each do |val, key|
|
||||
obj[key] = val
|
||||
end
|
||||
obj.after_parse
|
||||
obj
|
||||
end
|
||||
|
||||
|
@@ -309,4 +309,8 @@ module Netlink
|
||||
IPQM_VERDICT = 18
|
||||
IPQM_PACKET = 19
|
||||
IPQM_MAX = 20
|
||||
|
||||
# linux/netfilter_ipv4/ipt_ULOG.h
|
||||
ULOG_MAC_LEN = 80
|
||||
ULOG_PREFIX_LEN = 32
|
||||
end
|
||||
|
@@ -16,14 +16,18 @@ module Netlink
|
||||
field :timestamp_sec, :long
|
||||
field :timestamp_usec, :long
|
||||
field :hook, :uint
|
||||
field :indev_name, :pattern => "Z#{IFNAMSIZ}", :default => EMPTY_STRING
|
||||
field :outdev_name, :pattern => "Z#{IFNAMSIZ}", :default => EMPTY_STRING
|
||||
field :indev_name, :dev_name
|
||||
field :outdev_name, :dev_name
|
||||
field :hw_protocol, :ns
|
||||
field :hw_type, :ushort
|
||||
field :hw_addrlen, :uchar
|
||||
field :hw_addr, :pattern => "a8", :default => EMPTY_STRING
|
||||
field :data_len, :size_t
|
||||
field :payload, :binary # TODO: clip to data_len
|
||||
field :payload, :binary
|
||||
|
||||
def after_parse #:nodoc:
|
||||
payload.slice!(data_len..-1) if payload.length > data_len
|
||||
end
|
||||
end
|
||||
|
||||
# struct ipq_verdict_msg
|
||||
|
@@ -18,11 +18,15 @@ module Netlink
|
||||
# Use RtattrMessage instead for messages which are followed by variable rtattrs.
|
||||
class Message < CStruct
|
||||
# Map of numeric message type code => message class
|
||||
# (TODO: should these be scoped to NETLINK_* protocol id?)
|
||||
CODE_TO_MESSAGE = {}
|
||||
|
||||
# Define which message type code(s) to build using this structure
|
||||
def self.code(*codes)
|
||||
codes.each { |code| CODE_TO_MESSAGE[code] = self }
|
||||
codes.each do |code|
|
||||
warn "Duplicate message code: #{code}" if CODE_TO_MESSAGE[code]
|
||||
CODE_TO_MESSAGE[code] = self
|
||||
end
|
||||
end
|
||||
|
||||
NLMSG_ALIGNTO_1 = NLMSG_ALIGNTO-1 #:nodoc:
|
||||
@@ -51,6 +55,8 @@ module Netlink
|
||||
# specify :pack and :unpack lambdas to do higher-level conversion
|
||||
# of field values.
|
||||
class RtattrMessage < Message
|
||||
define_type :dev_name, :pattern=>"Z#{IFNAMSIZ}", :default=>EMPTY_STRING
|
||||
|
||||
# L2 addresses are presented as ASCII hex. You may optionally include
|
||||
# colons, hyphens or dots.
|
||||
# IFInfo.new(:address => "00:11:22:33:44:55") # this is OK
|
||||
|
46
lib/netlink/nflog.rb
Normal file
46
lib/netlink/nflog.rb
Normal file
@@ -0,0 +1,46 @@
|
||||
require 'netlink/message'
|
||||
require 'netlink/nlsocket'
|
||||
|
||||
module Netlink
|
||||
ULOG_NL_EVENT = 111 # from ipv4/netfilter/ipt_ULOG.c
|
||||
|
||||
# struct ulog_packet_msg
|
||||
class UlogPacket < Message
|
||||
code ULOG_NL_EVENT
|
||||
|
||||
field :mark, :ulong
|
||||
field :timestamp_sec, :long
|
||||
field :timestamp_usec, :long
|
||||
field :hook, :uint
|
||||
field :indev_name, :dev_name
|
||||
field :outdev_name, :dev_name
|
||||
field :data_len, :size_t
|
||||
field :prefix, :pattern=>"Z#{ULOG_PREFIX_LEN}", :default=>EMPTY_STRING
|
||||
field :mac_len, :uchar
|
||||
field :mac, :pattern=>"a#{ULOG_MAC_LEN}", :default=>EMPTY_STRING
|
||||
field :payload, :binary
|
||||
|
||||
def after_parse #:nodoc:
|
||||
mac.slice!(mac_len..-1) if mac.length > mac_len
|
||||
payload.slice!(data_len..-1) if payload.length > mac_len
|
||||
end
|
||||
end
|
||||
|
||||
module NFLog
|
||||
class Socket < NLSocket
|
||||
# Create a socket to listen for ulog packets. You must pass :group=>N
|
||||
# (where N is 1 to 32) or :groups=>bitmap to listen on multiple groups
|
||||
def initialize(opt={})
|
||||
unless opt[:groups]
|
||||
opt[:groups] = 1 << (opt.fetch(:group) - 1)
|
||||
end
|
||||
super(opt.merge(:protocol => Netlink::NETLINK_NFLOG))
|
||||
end
|
||||
|
||||
# Receive packets and yield them to the block
|
||||
def dequeue_packets(&blk)
|
||||
receive_stream(ULOG_NL_EVENT, &blk)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Reference in New Issue
Block a user