autodrop 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ChangeLog ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,75 @@
1
+ # -*-ruby-*-
2
+
3
+ FILES = [
4
+ 'ChangeLog',
5
+ 'Rakefile',
6
+ 'bin/autodrop',
7
+ 'bin/autodrop.rb',
8
+ 'conf/autodrop.conf.default',
9
+ 'doc/README.jp.txt',
10
+ 'doc/README.txt',
11
+ 'misc/autodrop.sh',
12
+ ]
13
+
14
+ desc "Same as 'rake bin/autodrop'"
15
+ task :default => [ "bin/autodrop" ]
16
+
17
+ desc "Make bin/autodrop"
18
+ file "bin/autodrop" do
19
+ sh "cp -f bin/autodrop.rb bin/autodrop"
20
+ sh "chmod 755 bin/autodrop"
21
+ end
22
+
23
+ desc "Do distclean"
24
+ task :distclean => [ :clobber_package ] do
25
+ sh "rm -f bin/autodrop"
26
+ end
27
+
28
+ task :gem => [ "bin/autodrop" ]
29
+ require 'rubygems'
30
+ require 'rake/gempackagetask'
31
+ spec = Gem::Specification.new do |s|
32
+ s.name = "autodrop"
33
+ s.version = "0.1.0"
34
+ s.author = "NOZAWA Hiromasa"
35
+ s.summary = "Automatic iptables DROP daemon"
36
+ s.homepage = 'http://rubyforge.org/projects/autodrop'
37
+ s.rubyforge_project = 'autodrop'
38
+ s.files = FILES
39
+ s.bindir = 'bin'
40
+ s.executables = 'autodrop'
41
+ s.require_path = []
42
+ end
43
+ Rake::GemPackageTask.new(spec) do |pkg|
44
+ pkg.need_zip = true
45
+ pkg.need_tar = true
46
+ end
47
+
48
+ #
49
+ # for manual installation (without rubygem)
50
+ #
51
+
52
+ DEFAULT_BIN_INSTALL_DIR = '/usr/local/sbin'
53
+ DEFAULT_CONF_INSTALL_DIR = '/etc'
54
+
55
+ desc "Install (without rubygem)"
56
+ task :install => "bin/autodrop" do
57
+ bin_install_dir = ENV['BIN_INSTALL_DIR']
58
+ bin_install_dir ||= DEFAULT_BIN_INSTALL_DIR
59
+ conf_install_dir = ENV['CONF_INSTALL_DIR']
60
+ conf_install_dir ||= DEFAULT_CONF_INSTALL_DIR
61
+ directory bin_install_dir
62
+ directory conf_install_dir
63
+ sh "cp -f bin/autodrop #{bin_install_dir}/autodrop"
64
+ sh "cp -f conf/autodrop.conf.default #{conf_install_dir}/autodrop.conf.default"
65
+ end
66
+
67
+ desc "Uninstall (without rubygem)"
68
+ task :uninstall do
69
+ bin_install_dir = ENV['BIN_INSTALL_DIR']
70
+ bin_install_dir ||= DEFAULT_BIN_INSTALL_DIR
71
+ conf_install_dir = ENV['CONF_INSTALL_DIR']
72
+ conf_install_dir ||= DEFAULT_CONF_INSTALL_DIR
73
+ sh "rm -f #{bin_install_dir}/autodrop"
74
+ sh "rm -f #{conf_install_dir}/autodrop.conf.default"
75
+ end
data/bin/autodrop ADDED
@@ -0,0 +1,202 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'syslog'
5
+
6
+ DEFAULT_CONFFILE = '/etc/autodrop.conf'
7
+
8
+ $debug = false
9
+
10
+ def log msg
11
+ if $debug
12
+ puts "#{Time.now}: syslog: #{msg}"
13
+ else
14
+ if Syslog.opened?
15
+ Syslog.info msg
16
+ end
17
+ end
18
+ end
19
+
20
+ def debug msg
21
+ return unless $debug
22
+ puts "#{Time.now}: debug: #{msg}"
23
+ end
24
+
25
+ def terminate whymsg, status = 0
26
+ log "terminate (#{whymsg})"
27
+ exit! status
28
+ end
29
+
30
+ module Autodrop
31
+ # { ip => Dog obj }
32
+ @dogs = {}
33
+
34
+ def Autodrop.house ip
35
+ @dogs.delete ip
36
+ end
37
+
38
+ def Autodrop.watch
39
+ log "start watching '#{WATCH_FIFO_}'"
40
+ loop {
41
+ begin
42
+ File.open(WATCH_FIFO_, File::RDONLY | File::NONBLOCK) { |f|
43
+ ready = File.select([f])
44
+ if ready
45
+ line = ready[0][0].gets
46
+ ip = nil
47
+ MESSAGES_TO_WATCH.each { |msg|
48
+ ip = $1 if line =~ msg
49
+ }
50
+ if ip
51
+ if @dogs.has_key? ip
52
+ @dogs[ip].bark
53
+ else
54
+ @dogs[ip] = Dog.new(ip)
55
+ end
56
+ end
57
+ end
58
+ }
59
+ rescue Errno::ENOENT => ex
60
+ log "lost FIFO '#{WATCH_FIFO_}'. exit"
61
+ break
62
+ end
63
+ }
64
+ end
65
+ end # Autodrop
66
+
67
+ class Dog
68
+ def initialize ip
69
+ @ip = ip
70
+ @count = 1
71
+ @time = Time.now + INTERVAL
72
+ @thread = Thread.new {
73
+ debug "[#{@ip}] bark! (#{@count})"
74
+ loop {
75
+ if Time.now >= @time
76
+ debug "[#{@ip}] leave"
77
+ break
78
+ end
79
+ if @count >= COUNT_MAX
80
+ bite
81
+ break
82
+ end
83
+ debug "[#{@ip}] grrr..."
84
+ sleep 1
85
+ }
86
+ Autodrop.house @ip
87
+ debug "[#{@ip}] end"
88
+ }
89
+ end
90
+
91
+ def bark
92
+ @count += 1
93
+ @time = Time.now + INTERVAL
94
+ debug "[#{@ip}] bark! (#{@count})"
95
+ end
96
+
97
+ def bite
98
+ if $debug
99
+ log "DROP (#{@ip})"
100
+ return
101
+ end
102
+ if system(IPTABLES_PROGRAM, '-I', 'INPUT', '-s', @ip, '-j', 'DROP')
103
+ log "DROP (#{@ip})"
104
+ else
105
+ log "error (iptables fail)"
106
+ end
107
+ end
108
+ end # Dog
109
+
110
+ ### main
111
+
112
+ @conffile = nil
113
+ opts = OptionParser.new
114
+ opts.on("-c CONFFILE", "--config CONFFILE", String, /.*/,
115
+ "Configuration file",
116
+ "(default: '#{DEFAULT_CONFFILE}')") { |conffile|
117
+ @conffile = conffile
118
+ }
119
+ opts.on("-d", "--debug", nil, nil,
120
+ "Debug mode",
121
+ "+ no daemon",
122
+ "+ write logs to stdout",
123
+ "+ watch fifo named './fifo'") { |flag|
124
+ $debug = true
125
+ }
126
+ opts.parse! ARGV
127
+ opts = nil
128
+
129
+ @conffile ||= DEFAULT_CONFFILE
130
+ unless File.file? @conffile
131
+ puts "#{@conffile} does not exist."
132
+ exit 1
133
+ end
134
+
135
+ eval File.readlines(@conffile).join("\n")
136
+
137
+ unless File.executable? IPTABLES_PROGRAM
138
+ puts "#{IPTABLES_PROGRAM} is not executable."
139
+ exit 1
140
+ end
141
+
142
+ if $debug
143
+ WATCH_FIFO_ = 'fifo'
144
+ else
145
+ WATCH_FIFO_ = WATCH_FIFO
146
+ if Process.euid != 0
147
+ puts 'Run as root'
148
+ exit 1
149
+ end
150
+ end
151
+
152
+ begin
153
+ Syslog.open('autodrop', Syslog::LOG_PID|Syslog::LOG_CONS, Syslog::LOG_AUTH)
154
+ if $debug
155
+ Autodrop.watch
156
+ else
157
+ # daemonify self
158
+ Process.fork {
159
+ Process.setsid
160
+ Dir.chdir "/"
161
+ trap("SIGINT") { terminate 'SIGINT' }
162
+ trap("SIGTERM") { terminate 'SIGTERM' }
163
+ trap("SIGHUP") { terminate 'SIGHUP' }
164
+ STDIN.reopen "/dev/null"
165
+ STDOUT.reopen "/dev/null"
166
+ STDERR.reopen "/dev/null"
167
+ File.open(PIDFILE, 'w') {|f|
168
+ f.puts Process.pid
169
+ }
170
+ Autodrop.watch
171
+ }
172
+ end
173
+ rescue => ex
174
+ log "error (#{ex}). exit"
175
+ exit! 1
176
+ end
177
+
178
+ # Copyright (c) 2009, NOZAWA Hiromasa. All rights reserved.
179
+ #
180
+ # Redistribution and use in source and binary forms, with or without
181
+ # modification, are permitted provided that the following conditions
182
+ # are met:
183
+ #
184
+ # 1. Redistributions of source code must retain the above copyright
185
+ # notice, this list of conditions and the following disclaimer.
186
+ # 2. Redistributions in binary form must reproduce the above
187
+ # copyright notice, this list of conditions and the following
188
+ # disclaimer in the documentation and/or other materials provided
189
+ # with the distribution.
190
+ #
191
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
192
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
193
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
194
+ # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
195
+ # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
196
+ # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
197
+ # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
198
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
199
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
200
+ # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
201
+ # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
202
+ # POSSIBILITY OF SUCH DAMAGE.
data/bin/autodrop.rb ADDED
@@ -0,0 +1,202 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'syslog'
5
+
6
+ DEFAULT_CONFFILE = '/etc/autodrop.conf'
7
+
8
+ $debug = false
9
+
10
+ def log msg
11
+ if $debug
12
+ puts "#{Time.now}: syslog: #{msg}"
13
+ else
14
+ if Syslog.opened?
15
+ Syslog.info msg
16
+ end
17
+ end
18
+ end
19
+
20
+ def debug msg
21
+ return unless $debug
22
+ puts "#{Time.now}: debug: #{msg}"
23
+ end
24
+
25
+ def terminate whymsg, status = 0
26
+ log "terminate (#{whymsg})"
27
+ exit! status
28
+ end
29
+
30
+ module Autodrop
31
+ # { ip => Dog obj }
32
+ @dogs = {}
33
+
34
+ def Autodrop.house ip
35
+ @dogs.delete ip
36
+ end
37
+
38
+ def Autodrop.watch
39
+ log "start watching '#{WATCH_FIFO_}'"
40
+ loop {
41
+ begin
42
+ File.open(WATCH_FIFO_, File::RDONLY | File::NONBLOCK) { |f|
43
+ ready = File.select([f])
44
+ if ready
45
+ line = ready[0][0].gets
46
+ ip = nil
47
+ MESSAGES_TO_WATCH.each { |msg|
48
+ ip = $1 if line =~ msg
49
+ }
50
+ if ip
51
+ if @dogs.has_key? ip
52
+ @dogs[ip].bark
53
+ else
54
+ @dogs[ip] = Dog.new(ip)
55
+ end
56
+ end
57
+ end
58
+ }
59
+ rescue Errno::ENOENT => ex
60
+ log "lost FIFO '#{WATCH_FIFO_}'. exit"
61
+ break
62
+ end
63
+ }
64
+ end
65
+ end # Autodrop
66
+
67
+ class Dog
68
+ def initialize ip
69
+ @ip = ip
70
+ @count = 1
71
+ @time = Time.now + INTERVAL
72
+ @thread = Thread.new {
73
+ debug "[#{@ip}] bark! (#{@count})"
74
+ loop {
75
+ if Time.now >= @time
76
+ debug "[#{@ip}] leave"
77
+ break
78
+ end
79
+ if @count >= COUNT_MAX
80
+ bite
81
+ break
82
+ end
83
+ debug "[#{@ip}] grrr..."
84
+ sleep 1
85
+ }
86
+ Autodrop.house @ip
87
+ debug "[#{@ip}] end"
88
+ }
89
+ end
90
+
91
+ def bark
92
+ @count += 1
93
+ @time = Time.now + INTERVAL
94
+ debug "[#{@ip}] bark! (#{@count})"
95
+ end
96
+
97
+ def bite
98
+ if $debug
99
+ log "DROP (#{@ip})"
100
+ return
101
+ end
102
+ if system(IPTABLES_PROGRAM, '-I', 'INPUT', '-s', @ip, '-j', 'DROP')
103
+ log "DROP (#{@ip})"
104
+ else
105
+ log "error (iptables fail)"
106
+ end
107
+ end
108
+ end # Dog
109
+
110
+ ### main
111
+
112
+ @conffile = nil
113
+ opts = OptionParser.new
114
+ opts.on("-c CONFFILE", "--config CONFFILE", String, /.*/,
115
+ "Configuration file",
116
+ "(default: '#{DEFAULT_CONFFILE}')") { |conffile|
117
+ @conffile = conffile
118
+ }
119
+ opts.on("-d", "--debug", nil, nil,
120
+ "Debug mode",
121
+ "+ no daemon",
122
+ "+ write logs to stdout",
123
+ "+ watch fifo named './fifo'") { |flag|
124
+ $debug = true
125
+ }
126
+ opts.parse! ARGV
127
+ opts = nil
128
+
129
+ @conffile ||= DEFAULT_CONFFILE
130
+ unless File.file? @conffile
131
+ puts "#{@conffile} does not exist."
132
+ exit 1
133
+ end
134
+
135
+ eval File.readlines(@conffile).join("\n")
136
+
137
+ unless File.executable? IPTABLES_PROGRAM
138
+ puts "#{IPTABLES_PROGRAM} is not executable."
139
+ exit 1
140
+ end
141
+
142
+ if $debug
143
+ WATCH_FIFO_ = 'fifo'
144
+ else
145
+ WATCH_FIFO_ = WATCH_FIFO
146
+ if Process.euid != 0
147
+ puts 'Run as root'
148
+ exit 1
149
+ end
150
+ end
151
+
152
+ begin
153
+ Syslog.open('autodrop', Syslog::LOG_PID|Syslog::LOG_CONS, Syslog::LOG_AUTH)
154
+ if $debug
155
+ Autodrop.watch
156
+ else
157
+ # daemonify self
158
+ Process.fork {
159
+ Process.setsid
160
+ Dir.chdir "/"
161
+ trap("SIGINT") { terminate 'SIGINT' }
162
+ trap("SIGTERM") { terminate 'SIGTERM' }
163
+ trap("SIGHUP") { terminate 'SIGHUP' }
164
+ STDIN.reopen "/dev/null"
165
+ STDOUT.reopen "/dev/null"
166
+ STDERR.reopen "/dev/null"
167
+ File.open(PIDFILE, 'w') {|f|
168
+ f.puts Process.pid
169
+ }
170
+ Autodrop.watch
171
+ }
172
+ end
173
+ rescue => ex
174
+ log "error (#{ex}). exit"
175
+ exit! 1
176
+ end
177
+
178
+ # Copyright (c) 2009, NOZAWA Hiromasa. All rights reserved.
179
+ #
180
+ # Redistribution and use in source and binary forms, with or without
181
+ # modification, are permitted provided that the following conditions
182
+ # are met:
183
+ #
184
+ # 1. Redistributions of source code must retain the above copyright
185
+ # notice, this list of conditions and the following disclaimer.
186
+ # 2. Redistributions in binary form must reproduce the above
187
+ # copyright notice, this list of conditions and the following
188
+ # disclaimer in the documentation and/or other materials provided
189
+ # with the distribution.
190
+ #
191
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
192
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
193
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
194
+ # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
195
+ # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
196
+ # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
197
+ # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
198
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
199
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
200
+ # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
201
+ # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
202
+ # POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,17 @@
1
+ # configration file for autodrop
2
+ # -*-ruby-*-
3
+
4
+ # $1 must match with an IP address
5
+ MESSAGES_TO_WATCH =
6
+ [
7
+ # OpenSSH
8
+ /Invalid user [^\s]+ from (.+)/,
9
+ /Address (.+) maps to [^\s]+, but this does not map back to the address - POSSIBLE BREAK-IN ATTEMPT!/,
10
+ ]
11
+
12
+ COUNT_MAX = 3
13
+ INTERVAL = 10 # sec
14
+
15
+ IPTABLES_PROGRAM = '/sbin/iptables'
16
+ PIDFILE = '/var/run/autodrop.pid'
17
+ WATCH_FIFO = '/var/log/authfifo'
data/doc/README.jp.txt ADDED
@@ -0,0 +1,164 @@
1
+ autodrop README
2
+
3
+ NOZAWA Hiromasa, Tokyo, Japan
4
+
5
+
6
+ = 概要
7
+
8
+ ホストへのしつこいアクセスを iptables で弾くデーモン。
9
+
10
+ syslog のログを監視して、パターンにマッチするログを一定期間内に繰り返し
11
+ 生じさせるホストを iptables の DROP ルールでアクセス禁止にする。
12
+
13
+ 監視するログのパターン、ログの発生回数、発生回数のカウントを続ける期間
14
+ を設定できる。パターンは複数設定できる。
15
+
16
+ 複数のログファイルをポーリングしたり stat したりせずに、単一の名前つき
17
+ パイプを見るようになっている。このため syslogd が目的のログを名前つきパ
18
+ イプへ吐くように設定する必要がある (syslog.conf で '|' を使う)。
19
+
20
+ Ruby 製です。Ruby なので、というかスクリプト言語製なので本格的に高トラ
21
+ フィックな環境には向かないでしょう。でもウチでは毎日々々延々と 22 番を
22
+ 叩きにくる人たちをしっかり弾いてくれるので重宝してます。なかなか重宝す
23
+ るので公開してみます。
24
+
25
+ この手のツールの常として自分を自分のホストから締め出すことも可能なので
26
+ 注意してください。
27
+
28
+
29
+ = 必要なもの
30
+
31
+ * iptables なので linux
32
+ * syslogd
33
+ * ruby 1.8.6 あたり
34
+
35
+
36
+ = ライセンス
37
+
38
+ BSD
39
+
40
+
41
+ = インストール
42
+
43
+ gem install したあと設定ファイルを作る必要があります。
44
+ #! 行も必要なら書き換えてください。
45
+
46
+ *1. gem install autodrop
47
+
48
+ *2. cd <GEMDIR>/gems/autodrop-x.x.x/conf
49
+
50
+ *3. sudo cp autodrop.conf.default /etc
51
+
52
+ *6. /etc/autodrop.conf を編集
53
+
54
+
55
+ = 使い方
56
+
57
+ == 起動
58
+
59
+ root で実行するようになってます。
60
+
61
+ ------------------------------
62
+ $ sudo ruby autodrop.rb
63
+ ------------------------------
64
+
65
+ 設定ファイルのデフォルトは /etc/autodrop.conf です。
66
+ コマンドラインから指定すれば別の場所にある設定ファイルも使えます。
67
+
68
+ ------------------------------
69
+ $ ruby autodrop.rb -c /foo/bar/autodrop.conf
70
+ ------------------------------
71
+
72
+ 起動すると /var/run/autodrop.pid が作られます。
73
+
74
+ == 停止
75
+
76
+ ------------------------------
77
+ $ sudo kill `cat /var/run/autodrop.pid`
78
+ ------------------------------
79
+
80
+ == 稼働中
81
+
82
+ autodrop 自身もプレフィクス `autodrop' で起動、終了、DROP の発生を
83
+ syslog に吐きます。
84
+
85
+ 稼働中は iptables の INPUT テーブルに DROP ルールが溜まる一方になるので、
86
+ たまに手でクリアすることになるかと思います。定期的にクリアするような機
87
+ 能はありません。
88
+
89
+
90
+ = autodrop.conf
91
+
92
+ どの設定も省略不可。どれも単なる ruby の定数です。
93
+
94
+ * MESSAGES_TO_WATCH
95
+
96
+ 監視するメッセージのパターンを正規表現で書いた配列。
97
+ $1 がリモートホストの IP アドレスにマッチするようにする。
98
+
99
+ ------------------------------
100
+ MESSAGES_TO_WATCH =
101
+ [
102
+ # OpenSSH's
103
+ /Invalid user [^\s]+ from (.+)/,
104
+ /Address (.+) maps to.*POSSIBLE BREAK-IN ATTEMPT!/,
105
+ ]
106
+ ------------------------------
107
+
108
+ * COUNT_MAX
109
+
110
+ DROP するまでのマッチ回数。
111
+
112
+ ------------------------------
113
+ COUNT_MAX = 3
114
+ ------------------------------
115
+
116
+ * INTERVAL
117
+
118
+ マッチしたパターン (パターンと IP アドレスの組) についてカウン
119
+ トをとり続ける時間。秒で指定する。
120
+ マッチするたびに 0 に戻る。
121
+
122
+ ------------------------------
123
+ INTERVAL = 10
124
+ ------------------------------
125
+
126
+ * IPTABLES_PROGRAM
127
+
128
+ 用いる iptables を指定する。
129
+
130
+ ------------------------------
131
+ IPTABLES_PROGRAM = '/bin/iptables'
132
+ ------------------------------
133
+
134
+ * PIDFILE
135
+
136
+ pid ファイルのパス。
137
+
138
+ ------------------------------
139
+ PIDFILE = '/var/run/autodrop.pid'
140
+ ------------------------------
141
+
142
+ * WATCH_FIFO
143
+
144
+ 監視する名前つきパイプのパス。
145
+
146
+ ------------------------------
147
+ WATCH_FIFO = '/var/log/authfifo'
148
+ ------------------------------
149
+
150
+
151
+ = 参考: syslogd の設定例
152
+
153
+ パイプを作って、
154
+ ------------------------------
155
+ sudo mkfifo /var/log/authfifo
156
+ ------------------------------
157
+ syslog.conf に登録する。
158
+ ------------------------------
159
+ authpriv.* |/var/log/authfifo
160
+ ------------------------------
161
+
162
+ 「|」で名前つきパイプへの出力になる。詳しくは syslog.conf(5) で。
163
+
164
+ #eof
data/doc/README.txt ADDED
@@ -0,0 +1,165 @@
1
+ autodrop README
2
+
3
+ NOZAWA Hiromasa, Tokyo Japan
4
+
5
+
6
+ = About
7
+
8
+ Autodrop is a daemon, observes syslog logs and forbid accesses from
9
+ remote hosts who continue wrong attempt to our host like knocking port
10
+ 22 for 100,000,000 times a day. Autodrop uses iptables(8) and named
11
+ pipe from syslogd.
12
+
13
+ Autodrop adds DROP rule into iptables' INPUT table for the remote host
14
+ which generates log messages matched with same reguler expression more
15
+ than specified times in specified interval.
16
+
17
+ Multiple regular expression can be specified by config file. Also
18
+ matching count threshold and interval time to continue counting can be
19
+ customizable.
20
+
21
+ Autodrop watches a named pipe and not neither does polling nor stat(2)
22
+ on many log files. You need syslogd which can output logs to named
23
+ pipe.
24
+
25
+ Autodrop is written in Ruby scripting language then surely it will not
26
+ suit for very high traffic sites. However it works well to shut out
27
+ port 22 knockers for my small site.
28
+
29
+ Using autodrop can also shut out yourself from your host. Be careful.
30
+
31
+
32
+ = Requirement
33
+
34
+ * linux box (for iptables)
35
+ * syslogd (can output logs to named pipes)
36
+ * ruby 1.8.6 or later (I have not run autodrop on other versions)
37
+
38
+
39
+ = Licence
40
+
41
+ BSD
42
+
43
+
44
+ = Install
45
+
46
+ After doing 'gem install', you need to write config file.
47
+ Fix #! line in the script if necessary.
48
+
49
+ *1. gem install autodrop
50
+
51
+ *2. cd <GEMDIR>/gems/autodrop-x.x.x/conf
52
+
53
+ *3. sudo cp autodrop.conf.default /etc
54
+
55
+ *4. Edit /etc/autodrop.conf
56
+
57
+
58
+ = Usage
59
+
60
+ == Start
61
+
62
+ ------------------------------
63
+ $ sudo ruby autodrop.rb
64
+ ------------------------------
65
+
66
+ Default config file is /etc/autodrop.conf .
67
+ Another config file can be specified from command line.
68
+
69
+ ------------------------------
70
+ $ ruby autodrop.rb -c /foo/bar/autodrop.conf
71
+ ------------------------------
72
+
73
+ == Stop
74
+
75
+ ------------------------------
76
+ $ sudo kill `cat /var/run/autodrop.pid`
77
+ ------------------------------
78
+
79
+ == When Running
80
+
81
+ Autodrop itself also outputs syslog logs with prefix 'autodrop' when
82
+ started, stopped and each occurrences of DROP.
83
+
84
+ After running autodrop, iptables's INPUT table will filled with DROP
85
+ rules in few weeks or months but autodrop does not have ability to
86
+ clear them. Please do it by your hand when it required.
87
+
88
+
89
+ = autodrop.conf
90
+
91
+ All variables are not omit-able.
92
+ These are Ruby's constant variables.
93
+
94
+ * MESSAGES_TO_WATCH
95
+
96
+ Array of regular expressions.
97
+ Each expression must have $1 and it must match an IP address.
98
+
99
+ ------------------------------
100
+ MESSAGES_TO_WATCH =
101
+ [
102
+ # OpenSSH's
103
+ /Invalid user [^\s]+ from (.+)/,
104
+ /Address (.+) maps to.*POSSIBLE BREAK-IN ATTEMPT!/,
105
+ ]
106
+ ------------------------------
107
+
108
+ * COUNT_MAX
109
+
110
+ Matching count to do DROP.
111
+
112
+ ------------------------------
113
+ COUNT_MAX = 3
114
+ ------------------------------
115
+
116
+ * INTERVAL
117
+
118
+ Interval time to continue counting for a remote host matched
119
+ to a pattern. Specify in seconds.
120
+ Each interval timers are reset on each matches.
121
+
122
+ ------------------------------
123
+ INTERVAL = 10
124
+ ------------------------------
125
+
126
+ * IPTABLES_PROGRAM
127
+
128
+ iptables(8) command path.
129
+
130
+ ------------------------------
131
+ IPTABLES_PROGRAM = '/sbin/iptables'
132
+ ------------------------------
133
+
134
+ * PIDFILE
135
+
136
+ PID file path.
137
+
138
+ ------------------------------
139
+ PIDFILE = '/var/run/autodrop.pid'
140
+ ------------------------------
141
+
142
+ * WATCH_FIFO
143
+
144
+ Named pipe path to watch.
145
+
146
+ ------------------------------
147
+ WATCH_FIFO = '/var/log/authfifo'
148
+ ------------------------------
149
+
150
+
151
+ = Example: syslogd configuration
152
+
153
+ Create fifo,
154
+ ------------------------------
155
+ mkfifo /var/log/authfifo
156
+ ------------------------------
157
+ and add it to your syslog.conf
158
+ ------------------------------
159
+ authpriv.* |/var/log/authfifo
160
+ ------------------------------
161
+
162
+ `|' means `out put logs to this pipe'.
163
+ See your syslog.conf(5) for more details.
164
+
165
+ #eof
data/misc/autodrop.sh ADDED
@@ -0,0 +1,18 @@
1
+ #!/bin/sh
2
+
3
+ AUTODROP=/usr/local/sbin/autodrop
4
+ CONF=/etc/autodrop.conf
5
+ PIDFILE=/var/run/autodrop.pid
6
+
7
+ case "$1" in
8
+ start)
9
+ $AUTODROP -c $CONF
10
+ ;;
11
+ stop)
12
+ kill -TERM `cat ${PIDFILE}`
13
+ ;;
14
+ *)
15
+ echo "usage: $0 { start | stop }" >&2
16
+ exit 1
17
+ ;;
18
+ esac
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: autodrop
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - NOZAWA Hiromasa
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-10 00:00:00 +09:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email:
18
+ executables:
19
+ - autodrop
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - ChangeLog
26
+ - Rakefile
27
+ - bin/autodrop
28
+ - bin/autodrop.rb
29
+ - conf/autodrop.conf.default
30
+ - doc/README.jp.txt
31
+ - doc/README.txt
32
+ - misc/autodrop.sh
33
+ has_rdoc: false
34
+ homepage: http://rubyforge.org/projects/autodrop
35
+ post_install_message:
36
+ rdoc_options: []
37
+
38
+ require_paths:
39
+ - []
40
+
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ version:
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ requirements: []
54
+
55
+ rubyforge_project: autodrop
56
+ rubygems_version: 1.3.1
57
+ signing_key:
58
+ specification_version: 2
59
+ summary: Automatic iptables DROP daemon
60
+ test_files: []
61
+