ip_in_range 0.8 → 1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +80 -0
- data/bin/ip_in_range +31 -34
- data/doc/license.txt +9 -670
- data/ip_in_range.gemspec +17 -0
- data/lib/basic_logging.rb +170 -0
- data/lib/email.rb +11 -19
- data/lib/file_checking.rb +4 -10
- data/lib/ip_range.rb +9 -16
- data/lib/version.rb +19 -2
- metadata +10 -9
- data/lib/log.conf +0 -56
- data/lib/logging.rb +0 -198
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f78cc554313b637067339aa2d806c605b6b7c585281fda8b8cdea2cc8362b7cc
|
4
|
+
data.tar.gz: 69f993155150a984ff2adb49690d6e4da65bc5d550ce28c754a6a9142450da8c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6181974367f0bed559cd03efad8795f06476e610f847d72fa8b9896f70d70d2c7937d5b6010d3c3e343ea966281b9cbbe1aa8d8cf7e44f937ce0d444c8f8da11
|
7
|
+
data.tar.gz: 5ec959d9ce03441472a4a9da6f67a61c8ecfdc6f3e7d452d88292fdf48a284b0f024c8e2f404bd5f906029de234b08f849af569b5e7949c6e7e6983b0d104055
|
data/README.md
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# IP_In_Range
|
2
|
+
Test an IP-address against a IP-range
|
3
|
+
## SYNOPSIS
|
4
|
+
To test on address:
|
5
|
+
> **ip_in_range first_in_range last_in_range ip_to_check**
|
6
|
+
|
7
|
+
To verify Received-headers:
|
8
|
+
> **ip_in_range < [email] first_in_range last_in_range
|
9
|
+
|
10
|
+
or
|
11
|
+
> **ip_in_range < [email] [range_list.txt]**
|
12
|
+
where range_list.txt contains a list of IP-ranges, one per line
|
13
|
+
|
14
|
+
## Description
|
15
|
+
You can pipe-in an email-message to filter and name a text-file as only
|
16
|
+
program-argument to ip_in_range. This text-file contains a simple list of
|
17
|
+
IP-ranges, one per line, like:
|
18
|
+
|
19
|
+
> 192.168.0.1 192.168.0.255
|
20
|
+
> Some Evil Exemplary Range: 192.168.2.100 192.168.2.168
|
21
|
+
> 192.200.12.20 192.200.12.100 I do no like this
|
22
|
+
> (...)
|
23
|
+
|
24
|
+
Text outside the IP-addresses is ignored by ip_in_range and can be used to comment an entry.
|
25
|
+
### Use with Procmail
|
26
|
+
Procmail can delegate tasks to external programs, either to react to a matching
|
27
|
+
filter or to test a condition which depends on the exit code of a program. Such
|
28
|
+
call of a program in the condition of a Procmail-filter is initiated with the **?**
|
29
|
+
flag. The recipe which tests if the Received-headers of a mail contain any
|
30
|
+
IP-address from a range that you want to filter:
|
31
|
+
|
32
|
+
> :0
|
33
|
+
> \* !FROM_DAEMON
|
34
|
+
> \* !FROM_MAILER
|
35
|
+
> \* !^X-Loop: my_mail@address
|
36
|
+
> \* 1^0 ? ip_in_range ~/.procmail/range_list.txt
|
37
|
+
> /home/[path to my mail-folder]/refused/ip_refused
|
38
|
+
|
39
|
+
This way, all mail which matches the filter will be written to a mail-folder “ip_refused” in the sub-directory “refused” of my mail-folder.
|
40
|
+
|
41
|
+
ip_in_range writes to STDOUT some informative log-message, i.e. the positiv
|
42
|
+
result of a test. You can thus know, which IP-address from a mail had been
|
43
|
+
found in which IP-range. To make these messages appear in the procmail
|
44
|
+
log-file, you can alter the condition in the above recipe to:
|
45
|
+
|
46
|
+
> \* 1^0 ? ip_in_range ~/.procmail/range_list.txt >> [logfile]
|
47
|
+
|
48
|
+
See the Procmail manual for more detailed explications.
|
49
|
+
|
50
|
+
### Remarks about the pertinence of this kind of filter
|
51
|
+
If you can, you should make your Mail-Transfer-Agent (MTA) filter mail and only
|
52
|
+
fetch the mail you want to read. If you do not know how to do this, then the filter
|
53
|
+
described above can be an alternative. If you do not use software like
|
54
|
+
Exim (sendmail), Postfix and the like be however aware of the limits of the
|
55
|
+
Procmail-solutions.
|
56
|
+
|
57
|
+
Even better are server-side filters that you would not have to activate anew
|
58
|
+
each time that you consult your mail-account.
|
59
|
+
|
60
|
+
Also, the author of IP_In_Range does not advocate filters against whole
|
61
|
+
IP-ranges as an efficient way to fight SPAM.
|
62
|
+
|
63
|
+
## Other Information
|
64
|
+
### Development and source code
|
65
|
+
IP_In_Range has been written in Ruby. As Ruby is an interpreted programming
|
66
|
+
language, the executable file and all those that it may refer to at one point
|
67
|
+
in time, are themselves the source-files of the current program-version. You
|
68
|
+
can open them in any text-editor to scrutinize the source-code. If you have
|
69
|
+
received the program as a Ruby-gem, you can also decompress a copy of the
|
70
|
+
gem-file with
|
71
|
+
*tar -x*, then *tar -xzf*.
|
72
|
+
|
73
|
+
**License**
|
74
|
+
IP_In_Range is distributed under the conditions of the WTF 2.0 or later version
|
75
|
+
of the license. See http://www.wtfpl.net/about/ for details.
|
76
|
+
|
77
|
+
**Author**
|
78
|
+
IP_In_Range has been developed by
|
79
|
+
Michael Uplawski <michael.uplawski@uplawski.eu>
|
80
|
+
Ω
|
data/bin/ip_in_range
CHANGED
@@ -2,38 +2,35 @@
|
|
2
2
|
#encoding: UTF-8
|
3
3
|
=begin
|
4
4
|
/***************************************************************************
|
5
|
-
* ©2021-
|
5
|
+
* ©2021-2024, Michael Uplawski <michael.uplawski@uplawski.eu> *
|
6
6
|
* *
|
7
7
|
* This program is free software; you can redistribute it and/or modify *
|
8
|
-
* it under the terms of the
|
9
|
-
*
|
10
|
-
* (at your option) any later version. *
|
8
|
+
* it under the terms of the WTFPL 2.0 or later, see *
|
9
|
+
* http://www.wtfpl.net/about/ *
|
11
10
|
* *
|
12
11
|
* This program is distributed in the hope that it will be useful, *
|
13
12
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
14
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
15
|
-
* GNU General Public License for more details. *
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
16
14
|
* *
|
17
|
-
* You should have received a copy of the GNU General Public License *
|
18
|
-
* along with this program; if not, write to the *
|
19
|
-
* Free Software Foundation, Inc., *
|
20
|
-
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
21
15
|
***************************************************************************/
|
22
16
|
=end
|
17
|
+
|
23
18
|
require_relative '../lib/ip_range'
|
24
19
|
require_relative '../lib/email'
|
25
|
-
require_relative '../lib/
|
20
|
+
require_relative '../lib/basic_logging'
|
26
21
|
require_relative '../lib/file_checking'
|
27
22
|
|
28
|
-
|
29
|
-
|
23
|
+
# log on class level
|
24
|
+
extend BasicLogging
|
25
|
+
set_target(STDOUT)
|
26
|
+
set_level BasicLogging::INFO
|
30
27
|
|
31
28
|
def usage
|
32
29
|
prog = File.basename($0)
|
33
30
|
usage = "\tUsage: " << prog << ' first_in_range last_in_range ip_to_check'
|
34
31
|
usage << "\n\tExample: " << prog << ' 192.168.1.100 192.168.1.255 192.168.10.100'
|
35
|
-
usage << "\n\
|
36
|
-
usage << "\n\t
|
32
|
+
usage << "\n\tto verify Received-headers: cat mail | " << prog << " first_in_range last_in_range"
|
33
|
+
usage << "\n\t or: cat mail | " << prog << " <file>"
|
37
34
|
usage << "\n\t\t where \"file\" contains a list of ip-ranges."
|
38
35
|
end
|
39
36
|
|
@@ -51,61 +48,61 @@ elsif ARGV.length == 2
|
|
51
48
|
if(!STDIN.tty?)
|
52
49
|
mail = FMail.new(ARGF.read)
|
53
50
|
else
|
54
|
-
|
51
|
+
error('No data to compare from STDIN – aborting!')
|
55
52
|
exit false
|
56
53
|
end
|
57
54
|
ips = mail.received.collect{|r| r.scan(IPR)}
|
58
55
|
ips.flatten!
|
59
|
-
|
56
|
+
debug( 'ips: ' << ips.join(', '))
|
60
57
|
ips.each do |ip|
|
61
58
|
exit true if ip_range.in_range?(ip)
|
62
59
|
end
|
63
|
-
|
60
|
+
info('not in range')
|
64
61
|
exit false
|
65
62
|
# 3) a text-file with ip-ranges, mail is piped in
|
66
63
|
elsif ARGV.length == 1
|
67
|
-
if(['-h', '--
|
64
|
+
if(['-h', '--help'].none?{|h| h == ARGV[0]})
|
68
65
|
list_file = ARGV[0]
|
69
66
|
ARGV.clear
|
70
67
|
if(!STDIN.tty?)
|
71
68
|
mail = FMail.new(ARGF.read)
|
72
69
|
else
|
73
|
-
|
70
|
+
error('No data waiting on STDIN – aborting!')
|
74
71
|
exit false
|
75
72
|
end
|
76
73
|
msg = File_Checking::file_check(list_file, [:file, :exist, :readable])
|
77
74
|
if msg
|
78
|
-
|
75
|
+
error( "File #{list_file} is unuseable: #{msg}. Aborting!" )
|
79
76
|
exit false
|
80
77
|
end
|
81
78
|
ranges = File.readlines(list_file)
|
82
79
|
ranges.each do |l|
|
83
|
-
|
84
|
-
if(!l.strip.empty?)
|
80
|
+
debug( "line is " << l)
|
81
|
+
if(!l.strip.empty? && !l.start_with?('#') )
|
85
82
|
begin
|
86
|
-
|
83
|
+
debug 'trying to extract an IP-range'
|
87
84
|
range = l.scan(IPR).flatten
|
88
|
-
|
85
|
+
debug('testing range ' << range.to_s)
|
89
86
|
rescue ArgumentError => msg
|
90
87
|
er = 'Cannot interpret IP-range ' << l
|
91
88
|
er << ': ' << msg
|
92
|
-
|
89
|
+
error(er)
|
93
90
|
rescue Exception => msg
|
94
|
-
|
91
|
+
error(msg)
|
95
92
|
else
|
96
|
-
|
93
|
+
debug( "range is " << range.to_s )
|
97
94
|
ip_range = IPRange.new(range)
|
98
|
-
|
95
|
+
debug( "testing ip_range " << ip_range.vrange.to_s )
|
99
96
|
ips = mail.received.collect{|r| r.scan(IPR)}
|
100
97
|
ips.flatten!
|
101
|
-
|
98
|
+
debug( 'ips: ' << ips.join(', ') )
|
102
99
|
ips.each do |ip|
|
103
100
|
isso = ip_range.in_range?(ip)
|
104
101
|
msg = 'ip ' << ip << (isso ? ' is ' : ' is not ' ) << 'in range: ' << l
|
105
102
|
if isso
|
106
|
-
|
103
|
+
info("\n" + msg)
|
107
104
|
else
|
108
|
-
|
105
|
+
debug(msg)
|
109
106
|
end
|
110
107
|
exit isso if isso
|
111
108
|
end
|
@@ -117,7 +114,7 @@ elsif ARGV.length == 1
|
|
117
114
|
puts usage
|
118
115
|
end
|
119
116
|
else
|
120
|
-
|
121
|
-
|
117
|
+
warn( "ERROR! Arguments missing" )
|
118
|
+
info( usage)
|
122
119
|
exit false
|
123
120
|
end
|