Новые возможности мониторинга событий в Windows Server 2008 Андрей Бирюков winrm quickconfig winrm quickconfig wecutil qc ----------------------------------------------------------------------------------------------------------------- Мониторинг активности хостов Антон Борисов $ ping 10.66.2.1 $ telnet 10.66.2.1 22 $ telnet 10.66.2.1 80 # chmod +x ./netwhistler2.10.bin # ./netwhistler2.10.bin $ /usr/local/netwhistler/netwhistler.sh # cd /usr/ports/net-mgmt/netmond # make && make install && make clean netmond_enable="YES" 1) RootDir "/var/netmon" 2) Polling 60 3) Timeout 2 4) Retries 3 5) Saving 300 6) TimeFmt "%H:%M:%S" 7) Group "local" { # Разрешить хосту с DNS-именем localhost 8) Permit "^localhost$" # Рарешить хосту по IP-адресу 9) Permit "^127\\.0\\.0\\.1$" # запретить всем – по умолчанию 10) Deny ".*" 11)} 12) Group "remote" { 13) Permit "^192\\.168\\.1\\.*" 14)} 15) NetState { # NetState server port number (mandatory) 16) Port 3333 # Client timeout (optional) 17) Timeout 30 # The number of Group references is unlimited 18) Group "local" # Match is done from top to bottom 19) Group "remote" 20)} 21) Method "http" { 22) tcp port 80 23) ChatScript { 24) Send "GET $1 HTTP/1.0\r\n\r\n" 25) Expect "^HTTP/1.1 200 OK$" 26) } 27)} 28) Method "pop3" { 29) tcp port 110 30) ChatScript { Send "" Expect "^\\+OK " Send "QUIT\r\n" Expect "" } 31)} 32) Method "smtp" { 33) tcp port 25 34) ChatScript { Send "" Expect "^220-" Send "QUIT\r\n" Expect "" } 35)} 36) Method "ftp" { 37) tcp port 21 38) ChatScript { Send "" Expect "^220 " Send "QUIT\r\n" Expect "" } 39)} 40) Method "ssh" { 41) tcp port 22 42) ChatScript { Send "" Expect "^SSH-" Send "QUIT\r\n" Expect "" } 43)} 44) Method "vnc" { 45) tcp port 5900 46) ChatScript { Send "" Expect "^RFB" Send "\r\n\r\n\r\n\r\n\r\n\r\n" } 47)} 48) Save "change-state-alarm" { 49) Pipe "mail -s \"$0\" root" 50) State "$time $1 $name $state" 51)} 52) Save "icmp-echo-alarm" { 53) File "%Y.%m.%d" 54) State "$time $0 $name $state" 55) } dhcping -s 192.168.0.203 -c 192.168.0.201 -v -i 56) Object "DHCP-Server1" { 57) Address "192.168.0.201" 58) Method Ping 59) Save "icmp-echo-alarm" "DHCP-Server1 ping" 60) Service "pop3" { 61) Method "pop3" 62) Save "icmp-echo-alarm" "DHCP-Server1 pop3" 63) } 64) Service "http" { 65) Method "http" "/index.html" 66) Save "icmp-echo-alarm" "DHCP-Server1 http" 67) } 68)} 69) Object "Unit1" { 70) Address "192.168.0.101" 71) Method Ping 72) Save "icmp-echo-alarm" "Unit1 ping" 73)} 74) Object "Host-51" { 75) Address "192.168.0.51" 76) Method Ping 77) Save "icmp-echo-alarm" "Host-51 ping" 78) Service "vnc" { 79) Method "vnc" 80) Save "icmp-echo-alarm" "Host-51 vnc" 81) } 82)} # tail -f /var/netmon/Host-51/2008.10.31 $ telnet 127.00.00.1 3333 any :* Save "down-alarm" { Exec "/root/system/pager.sh" When "$state == \"DOWN\"" 300 "$1 $name $state 5 minutes" } $ telnet 192.168.1.1 # cat /proc/uptime # ps afx 1) #!/usr/local/bin/expect -f 2) set host 192.168.1.1 3) set user username_to_login 4) set pass password_to_login 5) spawn telnet "$host" 6) expect "login:" 7) send "$user\r" 8) expect "word:" 9) send "$pass\r" 10) expect "#" 11) send "ifconfig\r" 12) send "exit\r" 13) interact send "reboot\r" # cat /root/system/pager2.sh #!/bin/sh REBOOT_TEXT=/root/system/modem_reboot.txt NC=/usr/bin/nc CAT=/bin/cat $CAT $REBOOT_TEXT | $NC 192.168.1.1 80 # cat /root/system/modem_reboot.txt GET /rebootinfo.cgi HTTP/1.1 Host: localhost Authorization: Basic aGVsbG86dGhlcmUK $ echo «username_to_login:password_to_login» | base64 # cd /usr/ports/net-mgmt/tknetmon/ # make && make install && make clean $ export DISPLAY=myIP:0 $ wish8.4 /usr/local/lib/TkNetmon-2.0.7a/TkNetmon.tcl ----------------------------------------------------------------------------------------------------------------- bugtraq, стр. 25 im:///'%20-l%20c:\boot.ini%20-v http://www.foo.bar:9090/setup/setup-/../../log.jsp?log=info&mode=asc&lines=All ----------------------------------------------------------------------------------------------------------------- Белые списки в DSPAM Михаил Кондрин cvs -z3 -d :pserver:cvs@cvs.nuclearelephant.com:/usr/local/cvsroot login cvs -z3 -d :pserver:cvs@cvs.nuclearelephant.com:/usr/local/cvsroot co dspam ./configure --sysconfdir=/etc \ --prefix=/usr \ --with-dspam-home=/var/dspam \ --with-storage-driver=mysql_drv \ --with-mysql-includes=/usr/include/mysql \ --with-mysql-libraries=/usr/lib/mysql \ --enable-preferences-extension \ --enable-virtual-users \ --enable-debug \ --enable-verbose-debug \ --enable-daemon mailbox_transport = lmtp:unix:/var/dspam/dspam.sock require ["regex", "relational", "fileinto", "envelope", "imapflags"]; if header :contains ["X-DSPAM-Result"] "Spam" {addflag "\\Deleted"; fileinto "Junk"; stop;} Home /var/dspam Trust root Trust mail Trust cyrus StorageDriver /usr/lib/libmysql_drv.so # --- Cyrus-IMAP --- DeliveryHost /var/imap/socket/lmtp DeliveryProto LMTP # --- MySQL --- MySQLServer /var/run/mysql/mysql.sock MySQLPort 3306 MySQLUser dspam MySQLPass _dont_use_this_pass_ MySQLDb dspam # --- DSPAM daemon/client --- ServerMode auto ServerParameters "--deliver=innocent,spam" ServerDomainSocketPath "/var/dspam/dspam.sock" ClientHost /var/dspam/dspam.sock # --- Preferences --- ... Preference "spamAction=deliver" Preference "signatureLocation=message" Feature whitelist ... /usr/bin/dspam --daemon & #!/usr/bin/tclsh set imapuser "dspam" set imappasswd "_dont_use_this_pass_" set dspam "/usr/bin/dspam" set imaphost "mail.myrealm.ru" set domain "myrealm.ru" set spambox "spam" set hambox "ham" set otherpref "Other" #Пользовательские параметры оканчиваются здесь source /usr/local/bin/imap4.tcl proc processmail { message username spam } { #Обучение dspam global dspam set f [open "| $dspam --client --user $username --source=error --class=$spam --process" WRONLY] fconfigure $f -encoding binary -buffering none -blocking 0 puts $f $message flush $f close $f } proc get_message { stream num } { #формируем письмо из заголовков и тела письма ::imap4::fetch $stream $num header set h [::imap4::msginfo $stream $num header] ::imap4::fetch $stream $num text set h2 [::imap4::msginfo $stream $num text] return ${h}${h2} } set imap [::imap4::open $imaphost] ::imap4::login $imap $imapuser $imappasswd #Собираем ящики, доступные $imapuser ::imap4::request $imap {list "" "*"} while 1 { if { [::imap4::processline $imap] == "*" } { lappend userslist [lindex [split [lindex $::imap4::info($imap,lastline) end] "."] end-1] } else { break } } foreach user [lsort -unique $userslist] { #Обработка ящиков spam и ham foreach action [list "spam" "innocent"] { if { $action == "spam" } { set d ${otherpref}.${user}.${spambox} } else { set d ${otherpref}.${user}.${hambox} } ::imap4::select $imap \"$d\" set mn [::imap4::mboxinfo $imap exists] for {set i 1} {$i <= $mn} {incr i} { #извлекаем отдельные письма ::imap4::fetch $imap $i flags if { [lsearch [::imap4::msginfo $imap $i flags] Deleted ] >= 0 } { continue } if { ([lsearch [::imap4::msginfo $imap $i flags] Flagged ] >= 0)&($action == "innocent") } { whitelist_message $imap $i ${user}@${domain} } processmail [get_message $imap $i] ${user}@${domain} $action ::imap4::request $imap "store $i +flags \\deleted" ::imap4::getresponse $imap } if { $action == "spam" } { #очистка ящика spam ::imap4::request $imap "expunge" ::imap4::getresponse $imap } } } close $imap package require Expect spawn cyradm mail.myrealm.ru set prompt "\.ru> $" expect { -re $prompt } exp_send "lm user.*\r" while 1 { expect { -re {user\.([[:alnum:]]+)} { lappend users $expect_out(1,string) } -re $prompt { break } } } foreach v2 [lsort -unique $users] { exp_send "cm user.${v2}.spam;cm user.${v2}.ham\r" expect { -re $prompt } exp_send "sam user.${v2}.spam dspam lrswd\r" expect { -re $prompt } exp_send "sam user.${v2}.ham dspam lrsw\r" expect { -re $prompt } } EVENTS { ... trainspam cmd="/usr/local/bin/traindspam.tcl" period=60 ... } dummy:merged:user1@myrealm.ru,user2@myrealm@ru dspam_merge mike@myrealm.ru -o dummy cat | dspam --user dummy --class=spam --source=inoculation vaccine:inoculation:dummy,johndoe@myrealm.ru,mike@myrealm.ru shared-user:shared:user1@myrealm.ru,user2@myrealm.ru group-admin:shared,managed:user1,user2 proc whitelist_message { stream num user } { #Добавление отправителя в белый список ::imap4::fetch $stream $num from: set h From*[string trim [::imap4::msginfo $stream $num from:]] set h1 [lindex [regexp -inline {CRC: ([[:digit:]]*)} [exec /usr/bin/dspam_crc $h]] 1] exec mysql -u dspam -p privet_dont_use -h post dspam -e \\ 'update dspam_token_data natural left join dspam_virtual_uids set innocent_hits=10000, spam_hits=0 where token=$h1 and username=$user' } if allof ( header :value "ge" ["X-DSPAM-Probability"] "0.5", header :contains ["X-DSPAM-Result"] "Whitelisted") {fileinto "ham"; addflag "\\Flagged"; keep;} if header :contains ["X-DSPAM-Result"] "Whitelisted" {addflag "\\Flagged"; stop;} ----------------------------------------------------------------------------------------------------------------- OpenBSD: особенности организации VPN на основе набора протоколов IPsec Максим Гришков #sysctl net.inet.ip.forwarding=1 net.inet.ip.forwarding=1 #mkdir -m 700 /etc/ipsec #dd bs=64 count=1 if=/dev/urandom | hexdump -e '64/1 "%02x"' >/etc/ipsec/akey.local #dd bs=20 count=1 if=/dev/urandom | hexdump -e '20/1 "%02x"' >/etc/ipsec/ekey #dd bs=64 count=1 if=/dev/urandom | hexdump -e '64/1 "%02x"' >/etc/ipsec/akey.remote #scp /etc/ipsec/akey.local xxx.xxx.xxx.2:/etc/ipsec/akey.remote #scp /etc/ipsec/akey.remote xxx.xxx.xxx.2:/etc/ipsec/akey.local #scp /etc/ipsec/ekey xxx.xxx.xxx.2:/etc/ipsec/ekey #chmod 600 /etc/ipsec/{akey*,ekey} flow esp from 10.10.10.0/24 to 10.10.99.0/24 local xxx.xxx.xxx.1 peer xxx.xxx.xxx.2 type require esp from xxx.xxx.xxx.1 to xxx.xxx.xxx.2 spi 0xc9dbb83d:0xabd9da39 \ auth hmac-sha2-512 enc blowfish \ authkey file "/etc/ipsec/akey.local:/etc/ipsec/akey.remote" \ enckey file "/etc/ipsec/ekey:/etc/ipsec/ekey" flow esp from 10.10.99.0/24 to 10.10.10.0/24 local xxx.xxx.xxx.2 peer xxx.xxx.xxx.1 type require esp from xxx.xxx.xxx.2 to xxx.xxx.xxx.1 spi 0xabd9da39:0xc9dbb83d \ auth hmac-sha2-512 enc blowfish \ authkey file "/etc/ipsec/akey.local:/etc/ipsec/akey.remote" \ enckey file "/etc/ipsec/ekey:/etc/ipsec/ekey" #route add -net 10.10.99.0/24 xxx.xxx.xxx.2 #route add -net 10.10.10.0/24 xxx.xxx.xxx.1 #ipsecctl -vf /etc/ipsec.conf #ipsecctl -sa #netstat -rnf encap #tcpdump esp ipsec=YES [General] Listen-on= ххх.ххх.ххх.1 [Phase 1] ххх.ххх.ххх.2= ISAKMP-peer-B [Phase 2] Connections= IPsec-A-B [ISAKMP-peer-B] Phase= 1 Local-address= ххх.ххх.ххх.1 Address= ххх.ххх.ххх.2 Configuration= Default-main-mode Authentication= great_password [IPsec-A-B] Phase= 2 ISAKMP-peer= ISAKMP-peer-B Configuration= Default-quick-mode Local-ID= Net-A Remote-ID= Net-B [Net-A] ID-type= IPV4_ADDR_SUBNET Network= 10.10.10.0 Netmask= 255.255.255.0 [Net-B] ID-type= IPV4_ADDR_SUBNET Network= 10.10.99.0 Netmask= 255.255.255.0 [Default-main-mode] DOI= IPSEC EXCHANGE_TYPE= ID_PROT Transforms= 3DES-SHA [Default-quick-mode] EXCHANGE_TYPE= QUICK_MODE Suites= QM-ESP-3DES-SHA-PFS-SUITE [General] Listen-on= ххх.ххх.ххх.2 [Phase 1] ххх.ххх.ххх.1= ISAKMP-peer-A [Phase 2] Connections= IPsec-B-A [ISAKMP-peer-A] Phase= 1 Local-address= ххх.ххх.ххх.2 Address= ххх.ххх.ххх.1 Configuration= Default-main-mode Authentication= great_password [IPsec-B-A] Phase= 2 ISAKMP-peer= ISAKMP-peer-A Configuration= Default-quick-mode Local-ID= Net-B Remote-ID= Net-A [Net-A] ID-type= IPV4_ADDR_SUBNET Network= 10.10.10.0 Netmask= 255.255.255.0 [Net-B] ID-type= IPV4_ADDR_SUBNET Network= 10.10.99.0 Netmask= 255.255.255.0 [Default-main-mode] DOI= IPSEC EXCHANGE_TYPE= ID_PROT Transforms= 3DES-SHA [Default-quick-mode] EXCHANGE_TYPE= QUICK_MODE Suites= QM-ESP-3DES-SHA-PFS-SUITE KeyNote-Version: 2 Authorizer: "POLICY" Licensees: "passphrase:great_password" Conditions: app_domain == "IPsec policy" && esp_present == "yes" && esp_enc_alg != "null" -> "true"; #chmod 600 /etc/isakmpd/isakmpd* #isakmpd -d isakmpd="-d" #openssl req -x509 -days 365 -newkey rsa:1024 -keyout /etc/ssl/private/ca.key -out /etc/ssl/ca.crt $openssl req -new -newkey rsa:1024 -nodes -keyout xxx.xxx.xxx.1.key -out xxx.xxx.xxx.1.csr $export CERTIP=xxx.xxx.xxx.1 $openssl x509 -req -days 365 -in $CERTIP.csr -CA /etc/ssl/ca.crt -CAkey /etc/ssl/private/ca.key -CAcreateserial -extfile /etc/ssl/x509v3.cnf -extensions x509v3_IPAddr -out $CERTIP.crt [General] Listen-on= xxx.xxx.xxx.1 [X509-certificates] CA-directory= /etc/isakmpd/ca/ Cert-directory= /etc/isakmpd/certs/ Private-key= /etc/isakmpd/private/xxx.xxx.xxx.1.key [Phase 1] xxx.xxx.xxx.2= ISAKMP-peer-B [Phase 2] Connections= IPsec-A-B [ISAKMP-peer-B] Phase= 1 Local-address= xxx.xxx.xxx.1 Address= xxx.xxx.xxx.2 Configuration= Default-main-mode [IPsec-A-B] Phase= 2 ISAKMP-peer= ISAKMP-peer-B Configuration= Default-quick-mode Local-ID= Net-A Remote-ID= Net-B [Net-A] ID-type= IPV4_ADDR_SUBNET Network= 10.10.10.0 Netmask= 255.255.255.0 [Net-B] ID-type= IPV4_ADDR_SUBNET Network= 10.10.99.0 Netmask= 255.255.255.0 [Default-main-mode] DOI= IPSEC EXCHANGE_TYPE= ID_PROT Transforms= 3DES-SHA-RSA_SIG [3DES-SHA-RSA_SIG] ENCRYPTION_ALGORITHM= 3DES_CBC HASH_ALGORITHM= SHA AUTHENTICATION_METHOD= RSA_SIG [Default-quick-mode] EXCHANGE_TYPE= QUICK_MODE Suites= QM-ESP-3DES-SHA-PFS-SUITE [General] Listen-on= ххх.ххх.ххх.2 [X509-certificates] CA-directory= /etc/isakmpd/ca/ Cert-directory= /etc/isakmpd/certs/ Private-key= /etc/isakmpd/private/ххх.ххх.ххх.2.key [Phase 1] ххх.ххх.ххх.1= ISAKMP-peer-A [Phase 2] Connections= IPsec-B-A [ISAKMP-peer-A] Phase= 1 Local-address= ххх.ххх.ххх.2 Address= ххх.ххх.ххх.1 Configuration= Default-main-mode [IPsec-B-A] Phase= 2 ISAKMP-peer= ISAKMP-peer-A Configuration= Default-quick-mode Local-ID= Net-B Remote-ID= Net-A [Net-A] ID-type= IPV4_ADDR_SUBNET Network= 10.10.10.0 Netmask= 255.255.255.0 [Net-B] ID-type= IPV4_ADDR_SUBNET Network= 10.10.99.0 Netmask= 255.255.255.0 [Default-main-mode] DOI= IPSEC EXCHANGE_TYPE= ID_PROT Transforms= 3DES-SHA-RSA_SIG [3DES-SHA-RSA_SIG] ENCRYPTION_ALGORITHM= 3DES_CBC HASH_ALGORITHM= SHA AUTHENTICATION_METHOD= RSA_SIG [Default-quick-mode] EXCHANGE_TYPE= QUICK_MODE Suites= QM-ESP-3DES-SHA-PFS-SUITE $openssl x509 -in /etc/isakmpd/ca/ca.crt -noout -subject subject=/C=RU/ST=MW/L=MOSCOW/O=SMPL/OU=IT DEPT/CN=RootCA/emailAddress=admin@pki.lan KeyNote-Version: 2 Authorizer: "POLICY" Licensees:"DN:/C=RU/ST=MW/L=MOSCOW/O=SMPL/OU=IT DEPT/CN=RootCA/emailAddress=admin@pki.lan" Conditions: app_domain == "IPsec policy" && esp_present == "yes" && esp_enc_alg != "null" -> "true"; ----------------------------------------------------------------------------------------------------------------- Сетевое сканирование с помощью МФУ от HP Иван Коробко Листинг 1. Раздел [Version] [Version] Signature = "$CHICAGO$" Class = IMAGE ClassGUID = {6bdd1fc6-810f-11d0-bec7-08002be2092f} Provider = "any" Листинг 2а. Определение списка устанавливаемых устройств [Manufacturer] "Hewlett-Packard"=HP,NTx86.5.1,NT.6.0 [HP] ; Windows XP [HP.NTx86.5.1] "HP LaserJet M2727nf MFP"=WIA_2727nf_NW,vid_03f0&pid_4D17&IP_SCAN ;Windows Vista [HP.NT.6.0] "HP LaserJet M2727nf MFP"=WIA_2727nf_NW,vid_03f0&pid_4D17&IP_SCAN Листинг 2б. Определение списка устанавливаемых устройств [Manufacturer] "Hewlett-Packard"=HP ; Все версии Windows [HP] "HP LaserJet M2727nf MFP"=WIA_2727nf,vid_03f0&pid_4D17&IP_SCAN Листинг 3. REG-файл для линковки МФУ с USB-интерфейсом к драйверу Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}\0002\DeviceData] "TulipIOType"=dword:00000005 "NetworkDeviceID"="\\macaddr:00170883C1CA\\port:1" "NetworkHostName"="" "PortID"="192.168.1.100" [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\Root\IMAGE\0002\Device Parameters] "NetworkDeviceID"="\\macaddr:00170883C1CA\\port:1" "PortID"="192.168.1.100" "NetworkHostName"=" " ----------------------------------------------------------------------------------------------------------------- Работаем с данными Active Directory из скриптов Часть вторая. Применение Perl и PHP Рашид Ачилов ldap_server=192.168.50.1 ldap_basedn="dc=shelton,dc=net" ldap_binddn=ldapread@SHELTON.NET ldap_password="cXdlcnR5ezEyM30K 0" ldap_common_filter="(&(sAMAccountName=*)(sAMAccountType=805306368)(telephoneNumber=*))" etcdir=/tmp sargdir=sarg2 sarglist=sargusers # Обратное преобразование строки пароля из конфигурационного файла # Вход: $1 conv_passwd (строка) – преобразованный пароль # Выход: password (строка) – раскодированный пароль sub demux_passwd { # Преобразованый пароль my $_deconved = shift(@_); my @_conved = split(/ /,$_deconved); # Дополнить преобразованную строку заполнителями if ( $_conved[1] != 0 ) { for (;$_conved[1] != 0; $_conved[1]--) { $_conved[0] = $_conved[0] . "="; } } # Раскодировать текст. decode_base64 присоединяет '\n' # к декодированному тексту, так что мы обрезаем его my $_iconved = decode_base64($_conved[0]); chomp($_iconved); return $_iconved; } # Перекодировка строки из UTF-8 в KOI8-R # Вход: $1 source (строка) – строка в кодировке UTF-8 # Выход: dest (строка) – строка в кодировке KOI8-R sub _from_utf8 { # Строка в кодировке UTF-8 my $_src = shift(@_); # Преобразовать в KOI8-R my $converter = Text::Iconv->new("utf-8", "koi8-r"); my $converted = $converter->convert($_src); return($converted); } # Разобрать командную строку # Вход: $1 _cmdref (ссылка на хэш) – ссылка на хэш с параметрами командной строки # Выход: rev (строка) – версия программы в текстовом виде sub parseOptions { # Ссылка на хэш с параметрами командной строки my $_cmdref = shift(@_); # Версия программы my $revisionNumber = sprintf("%d.%d", q$Revision: 1.33 $ =~ /(\d+)\.(\d+)/); # Разрешить обьединение различных опций после одного знака «-» Getopt::Long::Configure("bundling"); if ( !GetOptions( 'verbose|v' => \$_cmdref{'verbose'}, 'help|h' => \$_cmdref{'help'}, 'debug|x' => \$_cmdref{'debug'}, 'etcdir|e' => \$_cmdref{'etcdir'}, ) or $_cmdref{help} ) { usage($revisionNumber); exit(20); } return $revisionNumber; } # Размещение файла регистрационного журнала my $logfile = ">>./gensarguserlist.log"; # Размещение конфигурационного файла my $config = "./gensarguserlist.conf"; # Прочитать конфигурационный файл и импортировать все параметры в хэш _Config, # если конфигурационный файл существует и читается safe_logger(sprintf("Config file %s does not exist or does not readable", $_config), "DIE") if (! -e $config) || (! -r $config); Config::Simple->import_from($config, \%_Config) || die Config::Simple->error(); # Разобрать командную строку, вернуть номер версии программы и заполнить хэш параметров my $rev = parseOptions(\%_Config); # Открыть файл регистрационного журнала и отметить начало работы open(LOG,$logfile) || die "Sorry, I could not open log file $logfile for writing: $!\n"; safe_logger(sprintf("GenSargUserlist ver. %s started", $rev), ""); # Преобразовать пароль для подключения к LDAP в используемую форму my $_ldap_pwd = demux_passwd ($_Config{'default.ldap_password'}); # Подключиться к LDAP my $ldap = Net::LDAP->new($_Config{'default.ldap_server'}) || die "Cannot connect to LDAP server $_Config{'default.ldap_server'}: $!\n"; my $msg = $ldap->bind("$_Config{'default.ldap_binddn'}",password => "$_ldap_pwd"); # Если подключиться не удалось — работу продолжать незачем safe_logger(sprintf("[%d] %s: %s",$msg->code(),$msg->error_name(),$msg->error_text()), "DIE") if ($msg->is_error()); # Путь к файлу пользователей Sarg my $_sarglist = sprintf("%s/%s/%s",$_Config{'default.etcdir'},$_Config{'default.sargdir'},$_Config{'default.sarglist'}); # Путь к файлу пользователей Sarg my $_sarglist = sprintf("%s/%s/%s",$_Config{'default.etcdir'},$_Config{'default.sargdir'},$_Config{'default.sarglist'}); # Обработано записей my $_processed = 0; # Эти атрибуты будут запрошены из AD my $attrs = [ 'displayName', 'sAMAccountName' ]; # Отбираем данные в соответствии с общим фильтром my $result = $ldap->search ( base => "$_Config{'default.ldap_basedn'}", scope => "sub", filter => "$_Config{'default.ldap_common_filter'}", attrs => $attrs ); # Строка из файла Sarg userlist my $line; # Выходной массив, с логинами, уже присутствующими в Sarg userlist my @_presented; # Прочитано строк из файла Sarg userlist my $q_sarglist = 0; # Открыть Sarg userlist, если он существует. # Аварийно завершиться, если есть, но не читается if (-e $_sarglist) { open(ADD, $_sarglist) || safe_logger(sprintf("File %s " . "cannot open to read: %s", $_sarglist, $!), "DIE"); # Прочитать Sarg userlist и обработать каждую строку while (defined($line = )) { chomp($line); my @_str = split(/ /,$line); push(@_presented, $_str[0]); } $q_sarglist = @_presented; # Вывести количество записей, прочитанных из Sarg userlist и закрыть файл safe_logger(sprintf("Read %d records from file %s", $q_sarglist, $_sarglist),""); close(ADD); } # Открываем Sarg userlist для пополнения, создаем если отсутствует open(ADD,">>" . $_sarglist) || die "Sorry, I could not open file $_sarglist for writing: $!\n"; # Этот хэш будет использован для поиска среди логинов, уже пристутствующих в Sarg userlist my %seen; # Инициализируем хэш @seen{@_presented} = (); my $ex_value; # Внешний хэш содержит в поле ключа DN, в поле данных – адрес хэша с атрибутами foreach $ex_value (values %$entries) { # Взять логин my $_login = $$ex_value{'samaccountname'}; # Проверить его наличие в хэше из файла Sarg userlist if (not exists $seen{$$_login[0]}) { # Взять описание пользователя (фамилию имя и отчество одной строкой) my $_dispay = $$ex_value{'displayname'}; printf ADD "%s \t%s\n", $$_login[0], _from_utf8($$_dispay[0]); # Обработано записей $_processed++; } } close(ADD); $ldap->unbind(); close(LOG); // Обратное преобразование пароля // Вход: $converted (string) — преобразованный пароль // Выход: $passwd (string) — пароль в виде простого текста function demux_passwd($converted) { $_conved = explode(" ", $converted); // Дополнить строку нужным количеством заполнителей if ( $_conved[1] != 0 ) { for (;$_conved[1] != 0; $_conved[1]--) { $_conved[0] = $_conved[0] . "="; } } // Преобразовать получившуюся строку $_passwd = base64_decode($_conved[0]); return rtrim($_passwd); } // Вывести сообщение в файл журнала // Вход: $handle (filehandle) — хэндл открытого файла журнала // $msg (string) - строка для вывода // $severity (string) — если DIE, то выйти с ошибкой // Выход: ничего function safe_logger($handle, $msg, $severity) { $formatted = sprintf("%s [%s] gensargulist: %s\n", date("d/m/Y H:i:s"), posix_getpid(), $msg); fwrite($handle, $formatted); // Выход, если запрошено if ($severity == "DIE") die($formatted); } // Перекодировать строку из UTF-8 в KOI-8 // Вход: $1 source (string) - строка в UTF-8 // Выход: dest (string) - строка в KOI8-R function _from_utf8($source) { $converted = iconv("UTF-8", "KOI8-R", $source); return($converted); } // Файл регистрационного журнала $logfile = "./gensarguserlist.log"; // Конфигурационный файл $config = "./gensarguserlist.conf"; // Открыть файл журнала $handle = fopen($logfile, "a") or die(sprintf("Log file %s cannot open", $logfile)); // Прочитать конфигурационный файл и импортировать его переменные if (!is_readable($config)) safe_logger($handle, sprintf("Config file %s does not exist or does not readable", $config), "DIE"); $_config = parse_ini_file($config); // Преобразовать пароль для подключения к LDAP в читаемую форму $_ldap_pwd = demux_passwd($_config['ldap_password']); // Подключиться к серверу LDAP if (!$ldapconn = ldap_connect($_config['ldap_server'])) safe_logger($handle, sprintf("Cannot connect to LDAP server $s", $_config['ldap_server']), "DIE"); $ldapbind = ldap_bind($ldapconn, $_config['ldap_binddn'], $_ldap_pwd); // Путь к файлу Sarg userlist $_sarglist = sprintf("%s/%s/%s", $_config['etcdir'], $_config['sargdir'], $_config['sarglist']); // Обработано записей $_processed = 0; // Атрибуты, которые будут запрошены из AD $attrs = array("displayName", "sAMAccountName"); // Отобрать данные из AD $result = ldap_search($ldapconn, $_config['ldap_basedn'], $_config['ldap_common_filter'], $attrs); // Загрузить полученные данные $info = ldap_get_entries($ldapconn, $result); // Вывести количество записей в журнал safe_logger($handle, sprintf("Read %d records from server %s", $info["count"], $_config['ldap_server']), ""); // Если файл Sarg userlist существует, попробовать прочитать и разобрать его if (file_exists($_sarglist)) { // Выйти с ошибкой, если файл существует, но не читается if (!is_readable($_sarglist)) safe_logger($handle, sprintf("File %s cannot open to read", $_sarglist), "DIE"); // Прочитать файл в массив $lines = file($_sarglist); // Разбить каждую строку и поместить первый элемент в массив foreach ($lines as $_oneline) { $pieces = explode(" ", $_oneline); $presented[] = $pieces[0]; } // Ну и вывести количество строк в журнал safe_logger($handle, sprintf("Read %d records from file %s", count($presented), $_sarglist),""); } // Открыть Sarg userlist для пополнения $add = fopen($_sarglist, "a+") or safe_logger($handle, sprintf("Sorry, I could not open file %s for writing", $_sarglist), "DIE"); for ($i = 0; $i < $info["count"]; $i++) { // Если логин отсутствует в файле Sarg userlist if (!in_array($info[$i]["samaccountname"], $presented)) { // Вывести строку с данными по отсутствующему логину $oneadd = sprintf("%s \t%s\n", $info[$i]["samaccountname"], _from_utf8($info[$i]["displayname"])); fwrite($add, $oneadd); // Подсчитать количество добавленных строк $_processed++; } } // Записать результат в файл журнала if ($_processed) safe_logger($handle, sprintf("Added %d records in file %s", $_processed, $_sarglist), ""); ldap_unbind($ldapconn); fclose($add); fclose($handle); ----------------------------------------------------------------------------------------------------------------- Варианты очистки базы данных Андрей Луконькин Процедура УдалитьДокументы() Док = Создатьобъект("Документ.ПриказПоОтпуску"); Док.ВыбратьДокументы(); Пока Док.ПолучитьДокумент() = 1 Цикл Док.Удалить(1); КонецЦикла; КонецПроцедуры ----------------------------------------------------------------------------------------------------------------- Безопасность в сетях, построенных на Layer2-коммутаторах Александр Неупокоев switch# conf t switch(config)#int range f0/1 switch(config-if-range)#switchport mode access switch(config-if-range)#switchport port-security switch(config-if-range)#switchport port-security violation shutdown switch(config-if-range)#switchport port-security maximum 1 switch(config-if-range)#switchport port-security mac-address sticky show port-security catalyst#show port-security show port-security interface имя_интерфейса catalyst#show port-security int switch# conf t switch(conf)#int f0/1 switch(config-if)#switchport mode access switch(config-if)#switchport mode trunk switch(conf)#vlan 666 switch(config-vlan)#name Unconnected switch(config-vlan)#exit switch(conf)#int range f0/12 - 24 switch(config-if-range)#switchport access vlan 666 switch(config-if-range)#shut switch# conf t switch(config)#int range f0/1 - 24 switch(config-if-range)#spanning-tree portfast switch(config)#spanning-tree portfast bpduguard default switch(config)# int f0/1 switch(config-if)spanning-tree guard root switch(config-if)# switchport port-security mac-address 3234.2343.fa12 switch(config-if-range)#switchport port-security mac-address sticky switch# conf t switch(config)#int range f0/1 - 24 switch(config-if-range)#switchport mode access switch(config-if-range)#switchport port-security switch(config-if-range)#switchport port-security violation shutdown switch(config-if-range)#switchport port-security maximum 1 switch(config-if-range)#arp timeout 60 router#conf t router(config)#ip access-list extended pvlan router(config-ext-nacl)#deny ip 10.0.0.0 0.0.0.255 10.0.0.0 0.0.0.255 router(config-ext-nacl)#permit any any router(config-ext-nacl)#exit router(config)#int f0/1 router(config-if)#ip access-group pvlan in switch(config)# ip dhcp snooping switch(config)# ip dhcp snooping vlan 10 switch(config)#int f0/1 switch(config-if)#ip dhcp snooping trust switch(config)#ip dhcp snooping information option switch(config)#interface fa0/1 switch(config-if)#ip dhcp snooping limit rate 100 ----------------------------------------------------------------------------------------------------------------- WSGI – протокол связи веб-сервера с Python-приложением Дмитрий Васильев def simple_app(environ, start_response): status = '200 OK' response_headers = [('Content-type','text/plain')] start_response(status, response_headers) return ['Hello world!\n'] class AppClass: def __init__(self, environ, start_response): self.environ = environ self.start = start_response def __iter__(self): status = '200 OK' response_headers = [('Content-type','text/plain')] self.start(status, response_headers) yield "Hello world!\n" import os import sys def run_with_cgi(application): environ = dict(os.environ.items()) environ['wsgi.input'] = sys.stdin environ['wsgi.errors'] = sys.stderr environ['wsgi.version'] = (1, 0) environ['wsgi.multithread'] = False environ['wsgi.multiprocess'] = True environ['wsgi.run_once'] = True if environ.get('HTTPS', 'off') in ('on', '1'): environ['wsgi.url_scheme'] = 'https' else: environ['wsgi.url_scheme'] = 'http' headers_set = [] headers_sent = [] def write(data): if not headers_set: raise AssertionError("write() before start_response()") elif not headers_sent: # Перед выводом первых данных вывести # сохраненные заголовки status, response_headers = headers_sent[:] = headers_set sys.stdout.write('Status: %s\r\n' % status) for header in response_headers: sys.stdout.write('%s: %s\r\n' % header) sys.stdout.write('\r\n') sys.stdout.write(data) sys.stdout.flush() def start_response(status, response_headers, exc_info=None): if exc_info: try: if headers_sent: # Если заголовки были отправлены, # выкинуть исключение raise exc_info[0], exc_info[1], exc_info[2] finally: exc_info = None elif headers_set: raise AssertionError("Headers already set!") headers_set[:] = [status, response_headers] return write result = application(environ, start_response) try: for data in result: # Не отправляем заголовки, пока не видно тела if data: write(data) if not headers_sent: # Отправляем заголовки, если тело было пустое write('') finally: if hasattr(result, 'close'): result.close() def application(environ, start_response): lines = [] for key, value in environ.items(): lines.append("%s: %r" % (key, value)) start_response("200 OK", [("Content-Type", "text/plain")]) return ["\n".join(lines)] try: # Код обычного приложения status = "200 OK" response_headers = [("content-type", "text/plain")] start_response(status, response_headers) return ["OK"] except: # В реальном коде различные ошибки должны обрабатываться # различными обработчиками и не должен использоваться пустой except status = "500 Error" response_headers = [("content-type", "text/plain")] start_response(status, response_headers, sys.exc_info()) return ["Error"] -----------------------------------------------------------------------------------------------------------------