📄 is_spammer.bash
字号:
then # Build query order array. local -a _dns_ip _dns_ip[0]=${_si_input[3]} _dns_ip[1]=${_si_input[2]} _dns_ip[2]=${_si_input[1]} _dns_ip[3]=${_si_input[0]} eval $3=\(\ \$\{_dns_ip\[@\]\}\ \) fi return 0}# This function described in dot_array.bash.# dot_array <array_name>dot_array() { [ $# -eq 1 ] || return 1 # Single argument required. local -a _da_input eval _da_input=\(\ \$\{$1\[@\]\}\ \) local IFS=${DOT_IFS} local _da_output=${_da_input[@]} IFS=${WSP_IFS} echo ${_da_output} return 0}# This function described in file_to_array.bash# file_to_array <file_name> <line_array_name>file_to_array() { [ $# -eq 2 ] || return 1 # Two arguments required. local IFS=${NO_WSP} local -a _fta_tmp_ _fta_tmp_=( $(cat $1) ) eval $2=\( \$\{_fta_tmp_\[@\]\} \) return 0}# Columnized print of an array of multi-field strings.# col_print <array_name> <min_space> <tab_stop [tab_stops]>col_print() { [ $# -gt 2 ] || return 0 local -a _cp_inp local -a _cp_spc local -a _cp_line local _cp_min local _cp_mcnt local _cp_pos local _cp_cnt local _cp_tab local -i _cp local -i _cpf local _cp_fld # WARNING: FOLLOWING LINE NOT BLANK -- IT IS QUOTED SPACES. local _cp_max=' ' set -f local IFS=${NO_WSP} eval _cp_inp=\(\ \$\{$1\[@\]\}\ \) [ ${#_cp_inp[@]} -gt 0 ] || return 0 # Empty is easy. _cp_mcnt=$2 _cp_min=${_cp_max:1:${_cp_mcnt}} shift shift _cp_cnt=$# for (( _cp = 0 ; _cp < _cp_cnt ; _cp++ )) do _cp_spc[${#_cp_spc[@]}]="${_cp_max:2:$1}" #" shift done _cp_cnt=${#_cp_inp[@]} for (( _cp = 0 ; _cp < _cp_cnt ; _cp++ )) do _cp_pos=1 IFS=${NO_WSP}$'\x20' _cp_line=( ${_cp_inp[${_cp}]} ) IFS=${NO_WSP} for (( _cpf = 0 ; _cpf < ${#_cp_line[@]} ; _cpf++ )) do _cp_tab=${_cp_spc[${_cpf}]:${_cp_pos}} if [ ${#_cp_tab} -lt ${_cp_mcnt} ] then _cp_tab="${_cp_min}" fi echo -n "${_cp_tab}" (( _cp_pos = ${_cp_pos} + ${#_cp_tab} )) _cp_fld="${_cp_line[${_cpf}]}" echo -n ${_cp_fld} (( _cp_pos = ${_cp_pos} + ${#_cp_fld} )) done echo done set +f return 0}# # # # 'Hunt the Spammer' data flow # # # ## Application return codedeclare -i _hs_RC# Original input, from which IP addresses are removed# After which, domain names to checkdeclare -a uc_name# Original input IP addresses are moved here# After which, IP addresses to checkdeclare -a uc_address# Names against which address expansion run# Ready for name detail lookupdeclare -a chk_name# Addresses against which name expansion run# Ready for address detail lookupdeclare -a chk_address# Recursion is depth-first-by-name.# The expand_input_address maintains this list#+ to prohibit looking up addresses twice during#+ domain name recursion.declare -a been_there_addrbeen_there_addr=( '127.0.0.1' ) # Whitelist localhost# Names which we have checked (or given up on)declare -a known_name# Addresses which we have checked (or given up on)declare -a known_address# List of zero or more Blacklist servers to check.# Each 'known_address' will be checked against each server,#+ with negative replies and failures suppressed.declare -a list_server# Indirection limit - set to zero == no limitindirect=${SPAMMER_LIMIT:=2}# # # # 'Hunt the Spammer' information output data # # # ## Any domain name may have multiple IP addresses.# Any IP address may have multiple domain names.# Therefore, track unique address-name pairs.declare -a known_pairdeclare -a reverse_pair# In addition to the data flow variables; known_address#+ known_name and list_server, the following are output to the#+ external graphics interface file.# Authority chain, parent -> SOA fields.declare -a auth_chain# Reference chain, parent name -> child namedeclare -a ref_chain# DNS chain - domain name -> addressdeclare -a name_address# Name and service pairs - domain name -> servicedeclare -a name_srvc# Name and resource pairs - domain name -> Resource Recorddeclare -a name_resource# Parent and Child pairs - parent name -> child name# This MAY NOT be the same as the ref_chain followed!declare -a parent_child# Address and Blacklist hit pairs - address->serverdeclare -a address_hits# Dump interface file datadeclare -f _dot_dump_dot_dump=pend_dummy # Initially a no-op# Data dump is enabled by setting the environment variable SPAMMER_DATA#+ to the name of a writable file.declare _dot_file# Helper function for the dump-to-dot-file function# dump_to_dot <array_name> <prefix>dump_to_dot() { local -a _dda_tmp local -i _dda_cnt local _dda_form=' '${2}'%04u %s\n' local IFS=${NO_WSP} eval _dda_tmp=\(\ \$\{$1\[@\]\}\ \) _dda_cnt=${#_dda_tmp[@]} if [ ${_dda_cnt} -gt 0 ] then for (( _dda = 0 ; _dda < _dda_cnt ; _dda++ )) do printf "${_dda_form}" \ "${_dda}" "${_dda_tmp[${_dda}]}" >>${_dot_file} done fi}# Which will also set _dot_dump to this function . . .dump_dot() { local -i _dd_cnt echo '# Data vintage: '$(date -R) >${_dot_file} echo '# ABS Guide: is_spammer.bash; v2, 2004-msz' >>${_dot_file} echo >>${_dot_file} echo 'digraph G {' >>${_dot_file} if [ ${#known_name[@]} -gt 0 ] then echo >>${_dot_file} echo '# Known domain name nodes' >>${_dot_file} _dd_cnt=${#known_name[@]} for (( _dd = 0 ; _dd < _dd_cnt ; _dd++ )) do printf ' N%04u [label="%s"] ;\n' \ "${_dd}" "${known_name[${_dd}]}" >>${_dot_file} done fi if [ ${#known_address[@]} -gt 0 ] then echo >>${_dot_file} echo '# Known address nodes' >>${_dot_file} _dd_cnt=${#known_address[@]} for (( _dd = 0 ; _dd < _dd_cnt ; _dd++ )) do printf ' A%04u [label="%s"] ;\n' \ "${_dd}" "${known_address[${_dd}]}" >>${_dot_file} done fi echo >>${_dot_file} echo '/*' >>${_dot_file} echo ' * Known relationships :: User conversion to' >>${_dot_file} echo ' * graphic form by hand or program required.' >>${_dot_file} echo ' *' >>${_dot_file} if [ ${#auth_chain[@]} -gt 0 ] then echo >>${_dot_file} echo '# Authority reference edges followed and field source.' >>${_dot_file} dump_to_dot auth_chain AC fi if [ ${#ref_chain[@]} -gt 0 ] then echo >>${_dot_file} echo '# Name reference edges followed and field source.' >>${_dot_file} dump_to_dot ref_chain RC fi if [ ${#name_address[@]} -gt 0 ] then echo >>${_dot_file} echo '# Known name->address edges' >>${_dot_file} dump_to_dot name_address NA fi if [ ${#name_srvc[@]} -gt 0 ] then echo >>${_dot_file} echo '# Known name->service edges' >>${_dot_file} dump_to_dot name_srvc NS fi if [ ${#name_resource[@]} -gt 0 ] then echo >>${_dot_file} echo '# Known name->resource edges' >>${_dot_file} dump_to_dot name_resource NR fi if [ ${#parent_child[@]} -gt 0 ] then echo >>${_dot_file} echo '# Known parent->child edges' >>${_dot_file} dump_to_dot parent_child PC fi if [ ${#list_server[@]} -gt 0 ] then echo >>${_dot_file} echo '# Known Blacklist nodes' >>${_dot_file} _dd_cnt=${#list_server[@]} for (( _dd = 0 ; _dd < _dd_cnt ; _dd++ )) do printf ' LS%04u [label="%s"] ;\n' \ "${_dd}" "${list_server[${_dd}]}" >>${_dot_file} done fi unique_lines address_hits address_hits if [ ${#address_hits[@]} -gt 0 ] then echo >>${_dot_file} echo '# Known address->Blacklist_hit edges' >>${_dot_file} echo '# CAUTION: dig warnings can trigger false hits.' >>${_dot_file} dump_to_dot address_hits AH fi echo >>${_dot_file} echo ' *' >>${_dot_file} echo ' * That is a lot of relationships. Happy graphing.' >>${_dot_file} echo ' */' >>${_dot_file} echo '}' >>${_dot_file} return 0}# # # # 'Hunt the Spammer' execution flow # # # ## Execution trace is enabled by setting the#+ environment variable SPAMMER_TRACE to the name of a writable file.declare -a _trace_logdeclare _log_file# Function to fill the trace logtrace_logger() { _trace_log[${#_trace_log[@]}]=${_pend_current_}}# Dump trace log to file function variable.declare -f _log_dump_log_dump=pend_dummy # Initially a no-op.# Dump the trace log to a file.dump_log() { local -i _dl_cnt _dl_cnt=${#_trace_log[@]} for (( _dl = 0 ; _dl < _dl_cnt ; _dl++ )) do echo ${_trace_log[${_dl}]} >> ${_log_file} done _dl_cnt=${#_pending_[@]} if [ ${_dl_cnt} -gt 0 ] then _dl_cnt=${_dl_cnt}-1 echo '# # # Operations stack not empty # # #' >> ${_log_file} for (( _dl = ${_dl_cnt} ; _dl >= 0 ; _dl-- )) do echo ${_pending_[${_dl}]} >> ${_log_file} done fi}# # # Utility program 'dig' wrappers # # ### These wrappers are derived from the#+ examples shown in dig_wrappers.bash.## The major difference is these return#+ their results as a list in an array.## See dig_wrappers.bash for details and#+ use that script to develop any changes.## # ## Short form answer: 'dig' parses answer.# Forward lookup :: Name -> Address# short_fwd <domain_name> <array_name>short_fwd() { local -a _sf_reply local -i _sf_rc local -i _sf_cnt IFS=${NO_WSP}echo -n '.'# echo 'sfwd: '${1} _sf_reply=( $(dig +short ${1} -c in -t a 2>/dev/null) ) _sf_rc=$? if [ ${_sf_rc} -ne 0 ] then _trace_log[${#_trace_log[@]}]='# # # Lookup error '${_sf_rc}' on '${1}' # # #'# [ ${_sf_rc} -ne 9 ] && pend_drop return ${_sf_rc} else # Some versions of 'dig' return warnings on stdout. _sf_cnt=${#_sf_reply[@]} for (( _sf = 0 ; _sf < ${_sf_cnt} ; _sf++ )) do [ 'x'${_sf_reply[${_sf}]:0:2} == 'x;;' ] && unset _sf_reply[${_sf}] done eval $2=\( \$\{_sf_reply\[@\]\} \) fi return 0}# Reverse lookup :: Address -> Name# short_rev <ip_address> <array_name>short_rev() { local -a _sr_reply local -i _sr_rc local -i _sr_cnt IFS=${NO_WSP}echo -n '.'# echo 'srev: '${1} _sr_reply=( $(dig +short -x ${1} 2>/dev/null) ) _sr_rc=$? if [ ${_sr_rc} -ne 0 ] then _trace_log[${#_trace_log[@]}]='# # # Lookup error '${_sr_rc}' on '${1}' # # #'# [ ${_sr_rc} -ne 9 ] && pend_drop return ${_sr_rc} else # Some versions of 'dig' return warnings on stdout. _sr_cnt=${#_sr_reply[@]} for (( _sr = 0 ; _sr < ${_sr_cnt} ; _sr++ )) do [ 'x'${_sr_reply[${_sr}]:0:2} == 'x;;' ] && unset _sr_reply[${_sr}] done eval $2=\( \$\{_sr_reply\[@\]\} \) fi return 0}# Special format lookup used to query blacklist servers.# short_text <ip_address> <array_name>short_text() { local -a _st_reply local -i _st_rc local -i _st_cnt IFS=${NO_WSP}# echo 'stxt: '${1} _st_reply=( $(dig +short ${1} -c in -t txt 2>/dev/null) ) _st_rc=$? if [ ${_st_rc} -ne 0 ] then _trace_log[${#_trace_log[@]}]='# # # Text lookup error '${_st_rc}' on '${1}' # # #'# [ ${_st_rc} -ne 9 ] && pend_drop return ${_st_rc} else # Some versions of 'dig' return warnings on stdout. _st_cnt=${#_st_reply[@]} for (( _st = 0 ; _st < ${#_st_cnt} ; _st++ )) do [ 'x'${_st_reply[${_st}]:0:2} == 'x;;' ] && unset _st_reply[${_st}]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -