Первый взгляд. Windows 8 Server и Windows 8 Workstation Иван Коробко Листинг 1. Переименование локального компьютера Rename-Computer -NewName Onegin -Restrart ----------------------------------------------------------------------------------------------------------------- Почтовый сервер. Exim, Dovecot и RoundСube с интеграцией в Active Directory. Часть 2 Виталий Резников ########################################################### # ROUTERS CONFIGURATION # # Specifies how addresses are handled # ########################################################### #THE ORDER IN WHICH THE ROUTERS ARE DEFINED IS IMPORTANT! # An address is passed to each router in turn until it is # accepted begin routers # Поиск маршрута к хосту в DNS. Если маршрут не найден в DNS, # то это unroutable address. Не проверяются локальные домены dnslookup: driver = dnslookup domains = !+relay_to_domains : !+local_domains transport = remote_smtp ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8 more = no cannot_route_message = Remote domain not found in DNS # Группы (списки) рассылки. Поиск группы проходит строго # в определенной OU AD (чтобы минимизировать затраты на поиск) # по полю «mail» этой группы. Список адресов для рассылки # получается выборкой членов найденной группы AD с помощью # скрипта на Perl и извлечением у каждого адреса из поля mail ldap_distrib_group: driver = redirect domains = +relay_to_domains allow_fail allow_defer condition = ${if eqi{${quote:$local_part}@$domain}\ {${lookup ldapdn{LDAP_AUTH ldap:///ou=Группы рассылки,ou=Groups,ou=FIRMA-MARKET,dc=firma-market?mail?sub?(objectClass=group)}}}{no}{yes}} data = ${perl{get_mail_lists}{${quote:$local_part}@$domain}} # Поиск алиасов адресов. Просматривается поле # Web page – Other (LDAP-атрибут учетной записи: url) ldap_aliases: driver = redirect domains = +relay_to_domains allow_fail allow_defer data = ${lookup ldapm{LDAP_AUTH LDAP_BASE_SEARCH?mail?sub?(&(!(userAccountControl:1.2.840.113556.1.4.803:=2))\ (objectClass=user)(url=${quote_ldap:$local_part}${quote_ldap:@}${quote_ldap:$domain}))}} # Поиск адресов для перенаправления в другой ящик. Иногда # нужно перенаправлять почту одного сотрудника в ящик # другого (например, на время отпуска). В данном случае # почта падает в оба ящика. Проверяется поле Telephone # number – Other (атрибут otherTelephone) учетной записи # с целевым адресом. Если в этом поле есть один # или несколько e-mail, то письмо дублируется по ним ldap_forwarding: driver = redirect domains = +relay_to_domains allow_fail allow_defer data = ${lookup ldapm{LDAP_AUTH LDAP_BASE_SEARCH?otherTelephone?sub?(&(!(userAccountControl:1.2.840.113556.1.4.803:=2))\ (objectClass=user)(mail=${quote_ldap:$local_part}${quote_ldap:@}${quote_ldap:$domain}))}},\ ${quote:$local_part}@${quote:$domain} # Роутер Dovecot. В нем ищем незаблокированную учетную # запись в AD по условию совпадения поля «mail» этой # учетной записи обрабатываемому адресу. Если находим, # то сообщаем транспорту о расположении домашней директории # этого пользователя. Поскольку пользователи для локальной # системы сервера у нас виртуальные, то эти директории # будут служить только для хранения почты. Путь к ним: # /var/mail/, где – значение атрибута # samaccountName каждого пользователя AD. Если не находим, # то отправителю посылается NDR с текстом: Unknown address ldap_dovecot: debug_print = "R: ldap_local_user for $local_part@$domain" driver = accept domains = +relay_to_domains condition = ${if eq{}{${lookup ldapdn{LDAP_AUTH LDAP_BASE_SEARCH??sub?LDAP_MAIL_FILTER}}}{no}{yes}} transport = dovecot_lda router_home_directory = ${lookup ldapm{LDAP_AUTH LDAP_ BASE_SEARCH?samaccountName?sub?LDAP_MAIL_FILTER}{/var/mail/$value/}} user = 26 group = 26 more = no cannot_route_message = Unknown address # Роутер для локальных пользователей системы типа root и т.д. localuser: driver = accept domains = +local_domains check_local_user transport = local_delivery cannot_route_message = Unknown address ############################################################### # TRANSPORTS CONFIGURATION # ############################################################### # ORDER DOES NOT MATTER # # Only one appropriate transport is called for each delivery. # ############################################################### # A transport is used only when referenced from a router # that successfully handles an address. begin transports # Доставка на удаленные хосты – по SMTP remote_smtp: driver = smtp # Доставка средствами Dovecot – фактически просто раскладывание # писем по папкам виртуальных пользователей из AD dovecot_lda: driver = pipe command = /usr/local/libexec/dovecot/deliver -d $local_part@$domain message_prefix = message_suffix = delivery_date_add envelope_to_add return_path_add log_output user = mailnull temp_errors = 64 : 69 : 70: 71 : 72 : 73 : 74 : 75 : 78 # This transport is used for local delivery to user # mailboxes in traditional BSD mailbox format. # Доставка для локальных пользователей local_delivery: driver = appendfile file = /var/mail/UNIX/$local_part delivery_date_add envelope_to_add return_path_add group = mail user = $local_part mode = 0660 no_mode_fail_narrower PLAIN: driver = plaintext public_name = PLAIN server_prompts = : server_condition = ${if ldapauth{user="${quote_ldap_dn:$auth2}@LDAP_DOMAIN" pass=${quote:$auth3}ldap://LDAP_DOMAIN}{yes}{no}} server_set_id = $auth2 ########################################################### # AUTHENTICATION CONFIGURATION # ########################################################### begin authenticators dovecot_plain: driver = dovecot public_name = PLAIN server_socket = /var/run/dovecot/auth-client server_set_id = $auth2 dovecot_login: driver = dovecot public_name = LOGIN server_socket = /var/run/dovecot/auth-client server_set_id = $auth1 # Аутентификационный механизм Kerberos/GSSAPI. Этот тип # аутентификации появился у меня позже предыдущих,подробнее # о нем я расскажу в следующей части статьи. Отмечу лишь, # что SASL GSSAPI требует наличия секретного ключа для # сервиса smtp/ms01.firma-market в таблице /etc/krb5.keytab, # необходимого для формирования билетов Kerberos dovecot_gssapi: driver = dovecot public_name = GSSAPI server_socket = /var/run/dovecot/auth-client server_set_id = $auth1 ms01# /usr/local/etc/rc.d/exim reload ms01 [/usr/local/etc/exim/db]# cat blacklist # spammers domains *.pl *.it *.nl *.cl *.br ms01 [/usr/local/etc/exim/db]# cat dialup_hosts # dialup hosts ^.*dsl.* ^.*dialup.* ^.*dialin.* ^.*pool.* ^.*peer.* ^.*dhcp.* ^.*dynamic.* ^.*cable.* ^.*ppp.* ^.*cdma.* ^.*in-addr.* ^.*fbx.* ^.*kabel.* ^.*client.* ^.*klient.* ^.*user.* ^.*static.* ^.*speedy.* ^.*cdma.* ^.*catv.* ^.*customer.* ^.*generation.* ^\N.*host(\d|\-)\N ^\N.*[\-.]\d+[\-.]\d+.*\N ^\N.*\d{5,}.*\N ^\N^\d+.*\N ms01 [/usr/local/etc/exim/db]# cat whitelist 126.com 163.com alfa-hunter.ru alkor.co.ru biksib.ru ... ms01 [/usr/local/etc/exim/filters] cat system-filter logfile /var/log/exim/system-filter.log # Add second subject line with ***SPAM*** if message # detected as spam if $acl_c1 contains "1" then headers add "Old-Subject: $rh_subject:" headers remove "Subject" headers add "Subject: ***SPAM*** $rh_old-subject:" headers add "X-Spam-FM: YES" headers add "X-Spam-Report: Send HELO/EHLO and your name first" headers remove "Old-Subject" endif if $acl_c1 contains "2" then headers add "Old-Subject: $rh_subject:" headers remove "Subject" headers add "Subject: ***SPAM*** $rh_old-subject:" headers add "X-Spam-FM: YES" headers add "X-Spam-Report: Forbidden to use IP-address instead of the host name in HELO" headers remove "Old-Subject" endif ms01# exim –bt > dg_buh@firma-market.ru #!/bin/sh # List of logs in a format YYYYMMDD LIST_L =`ls /var/log/exim/ | grep main | cut -f 2 -d '-' | cut -f 1 -d '.'` # Today's date and date one month ago DATE_T=`date "+%Y%m%d"` DATE_M=`date -v-1m "+%Y%m%d"` # Number of logs NUM_L=`echo $LIST_L | wc -w` # Count i=1 # Search of names every log and delete while [ $i -le $NUM_L ] do LOG=`echo $LIST_L | cut -f $i -d ' '` if [ $LOG -lt $DATE_M ] then rm /var/log/exim/main-$LOG.log 2>/dev/null rm /var/log/exim/reject-$LOG.log 2>/dev/null fi i=`expr $i + 1` done ms01# cd /usr/ports/mail/dovecot ms01# make install clean ms01 [/usr/local/etc]# cat dovecot.conf ## Dovecot configuration file # Поддерживаемые протоколы protocols = imap managesieve # Разрешаем передачу пароля открытым текстом, нужно, если используем аутентификацию PLAIN disable_plaintext_auth = no ## ## Mailbox locations and namespaces ## # Расположение каталогов с почтой, если они явно не заданы в базе пользователей. # Значение переменной %h (home directory) берется из dovecot-ldap.conf mail_location = maildir:%h # UID/GID владельца каталога с почтовыми ящиками first_valid_uid = 26 last_valid_uid = 26 first_valid_gid = 26 last_valid_gid = 26 ## ## Maildir-specific settings ## # Копировать почту в другие директории, используя «жесткие ссылки». # Это намного быстрее, чем реальное копирование файла maildir_copy_with_hardlinks = yes ## ## IMAP specific settings ## protocol imap { # Подключаем плагин для автосоздания почтовых папок mail_plugins = autocreate mail_plugin_dir = /usr/local/lib/dovecot/imap imap_client_workarounds = delay-newmail netscape-eoh tb-extra-mailbox-sep } ## ## ManageSieve specific settings # Включаем протокол managesieve – для загрузки пользовательских скриптов sieve. # Для поддержки протокола managesieve нужно установить пакет dovecot-managesieve protocol managesieve { } ## LDA specific settings protocol lda { # Подключаем плагин sieve – для серверных скриптов (фильтров) на языке sieve mail_plugins = sieve mail_plugin_dir = /usr/local/lib/dovecot/lda debug = yes log_path = /var/log/dovecot/dovecot-deliver.log info_log_path = /var/log/dovecot/dovecot-deliver.log syslog_facility = mail ## Authentication processes # Формат имени пользователя (перевод в нижний регистр, удалять домен, если он задан) auth_username_format = %Ln # Секция с описанием механизмов и опций аутентификации auth default { # Возможные механизмы аутентификации: # plain login digest-md5 cram-md5 ntlm rpa apop a # nonymous gssapi otp skey gss-spnego # Включаем следующие mechanisms = plain login # База данных паролей, нужна для поиска и верификации паролей пользователей. # Для аутентификации будем использовать LDAP и поиск в AD passdb ldap { # Путь для конфигурационного файла LDAP. args = /usr/local/etc/dovecot-ldap.conf } # База данных пользователей, нужна для определения местоположения каталогов с почтой, # а также user/group ID для них.Самих пользователей (их логины и пути к ящикам) # будем искать по LDAP в AD. Также будем выполнять проверку на заполненность поля «mail» # в свойствах учетной записи AD userdb ldap { # Путь к конфигурационному файлу LDAP. В нем будет фильтр, выполняющий проверку # на заполненность поля «mail» в свойствах учетной записи AD args = /usr/local/etc/dovecot-ldap.conf } # Пользователь, от имени которого будет работать процесс аутентификации. # Этому пользователю нужен доступ к БД паролей user = root # Включаем возможность для экспорта интерфейса аутентификации в другие программы. # Слушающие сокеты будут созданы мастер-процессом Dovecot с использованием настроек из этого раздела socket listen { master { # Мастер-сокет предоставляет доступ базе пользователей. # В целях безопасности нельзя давать широкие права path = /var/run/dovecot/auth-master mode = 0600 # Пользователь/группа по умолчанию, для старта процесса dovecot-auth user = mailnull group = mail } client { # Клиентский сокет, как правило, безопасен для экспорта любому приложению. # Обычно используется для экспорта в ваш SMTP-сервер, чтобы использовать # его для команд SMTP AUTH. Наш Exim как раз будет использовать его path = /var/run/dovecot/auth-client mode = 0660 # чтобы Exim мог использовать процесс аутентификации # Dovecot, назначим права на него как у самого процесса Exim user = mailnull group = mail } } } ## Plugin settings # Настройки всех подключенных ранее плагинов plugin { # Укажем, как будут называться файлы, содержащие клиентские sieve-скрипты sieve=~/.dovecot.sieve # Каталог для хранения sieve-скриптов sieve_dir=~/sieve # (!)Размещение глобального скрипта. Если появляются # пользовательские скрипты, то эта опция игнорируется(!) sieve_global_path=/usr/local/etc/exim/filters/sieve-filter sieve_global_dir=/usr/local/etc/exim/filters/ # Опция, указывающая на серверный скрипт, который будет выполняться до пользовательских. # Он будет использоваться для перемещения спама в папку Junk. # Эта опция нужна, т.к. при появлении пользовательского скрипта, предыдущая опция игнорируется sieve_before=/usr/local/etc/exim/filters/sieve-filter # Autocreate plugin # Указанные папки будут создаваться автоматом при логине пользователя, и он будет автоматически на них подписан autocreate = Trash autocreate2 = Junk autocreate3 = Sent autocreate4 = Drafts autosubscribe = Trash autosubscribe2 = Junk autosubscribe3 = Sent autosubscribe4 = Drafts } ----------------------------------------------------------------------------------------------------------------- Виртуальное рабочее место с помощью VMware View 5.0. Часть 2 Антон Борисов Листинг 1. Клиент для сервера VMware View поддерживает перенаправление как графики, так и USB-устройств $ vmware-view --help vmware-view -s http://My_View_Server:80/ -u adm -d DCPROMO -p MyPass -q -n VM_PCOIP Листинг 2. Для проброса USB-соединений нужно вручную создать файл usb.link # echo "/usr/lib/vmware/vmware-view-usb \$* -o exid:vid2385pid5668" > /etc/vmware/usb.link # chmod 4755 /etc/vmware/usb.link # chmod 4755 /usr/lib/vmware/vmware-view-usb ----------------------------------------------------------------------------------------------------------------- Бесплатно в облака?! Сколько стоит создать свою облачную инфраструктуру? Сергей Крутских Volume Name: nfsvdi Volume Description: for_xcp Required Space: 51168 Filesystem /Volume type: ext3 # if [ -x /sbin/lvm.static ]; then # if /sbin/lvm.static vgscan --mknodes --ignorelockingfailure > /dev/null 2>&1 ; then # action $"Setting up Logical Volume Management:" /sbin/lvm.static vgchange -a y -ignorelockingfailure # fi # fi 192.168.1.25:/mnt/vg0/nfsvdi/disk/ /etc/init.d/xapi stop cp /opt/xensource/bin/xapi /opt/xensource/bin/xapi.orig /usr/bin/perl -pi -e 's/1\.1\.0/5.6.0/g' /opt/xensource/bin/xapi /etc/init.d/xapi start ----------------------------------------------------------------------------------------------------------------- Настройка L2TP/IPSec VPN-подключения между Linux и Windows Дмитрий Богомолов $ sudo apt-get install openswan xl2tpd $ cat /etc/ipsec.conf version 2.0 config setup nat_traversal=yes virtual_private=%v4:10.0.0.0/8,%v4:172.16.0.0/12,%v4:192.168.0.0/16,%v4:!192.168.21.0/24 oe=off protostack=netkey include /etc/ipsec.d/l2tp-psk.conf $ cat /etc/ipsec.d/l2tp-psk.conf conn L2TP-PSK authby=secret pfs=no auto=add keyingtries=3 rekey=no left=%defaultroute leftprotoport=17/1701 right=%any rightprotoport=17/0 conn L2TP-PSK-0.85 authby=secret pfs=no auto=add keyingtries=3 rekey=no left=%defaultroute leftprotoport=17/1701 right=192.168.0.85 rightprotoport=17/0 192.168.0.252 192.168.0.85: PSK "111111" 192.168.0.252 %any: PSK "000000" $ cat /etc/xl2tpd/xl2tpd.conf [lns default] ip range = 192.168.21.128-192.168.21.254 local ip = 192.168.21.100 length bit = yes require authentication = yes name = LinuxVPNServer ppp debug = no pppoptfile = /etc/ppp/options.l2tpd.lns $ cat /etc/ppp/options.l2tpd.lns lock noauth nomppe maxfail 0 lcp-echo-interval 60 lcp-echo-failure 4 nodefaultroute require-mschap-v2 noaccomp nopcomp proxyarp nobsdcomp nodeflate $ cat /etc/ppp/chap-secrets: ipsec * "000000" 192.168.21.128/25 ipsec2 * "000000" 192.168.21.150 config setup: ... virtual_private=%v4:10.0.0.0/8,%v4:172.16.0.0/12,%v4:192.168.0.0/16,%v4:192.168.1.0/24,%v4:!192.168.21.0/24 conn L2TP-PSK … rightsubnet=vhost:%no,%priv conn L2TP-PSK … leftnexthop=192.168.0.1 $ openssl req -new -out myvpn.req $ openssl x509 -inform DER -in myvpn.cer -outform PEM -out myvpn.pem $ openssl x509 -inform DER -in windowsCA.cer -outform PEM -out windowsCA.pem $ cp windowsCA.pem /etc/ipsec.d/cacerts $ cp myvpn.pem /etc/ipsec.d/certs $ cp private.pem /etc/ipsec.d/private/myvpnKey.pem conn L2TP-PSK … #Принимаем подключения только с внешнего интерфейса left = 192.168.0.252 include /etc/ipsec.d/l2tp-cert.conf $ cat /etc/ipsec.d/l2tp-cert.conf conn L2TP-X.509 authby=rsasig pfs=no auto=add rekey=no ikelifetime=8h keylife=1h type=transport left=192.168.0.252 leftid=%fromcert leftrsasigkey=%cert leftcert=/etc/ipsec.d/certs/myvpn.pem leftprotoport=17/1701 right=%any rightca=%same rightrsasigkey=%cert rightprotoport=17/1701 rightsubnet=vhost:%priv,%no : RSA /etc/ipsec.d/private/myvpnKey.pem "000000" $ openssl x509 -inform DER -in isa.cer -outform PEM -out isa.pem $ openssl crl -inform DER -in certcrl.cer -outform PEM -out certcrl.pem $ cp isa.pem /etc/ipsec.d/certs $ cp certcrl.pem /etc/ipsec.d/certs include /etc/ipsec.d/l2tp-cert-client.conf $ cat /etc/ipsec.d/l2tp-cert-client.conf conn L2TP-X.509-client keyingtries=%forever authby=rsasig pfs=no auto=start rekey=no ikelifetime=8h keylife=1h type=transport left=192.168.0.99 leftid=%fromcert leftrsasigkey=%cert leftcert=/etc/ipsec.d/certs/isa.pem leftprotoport=17/1701 right=192.168.0.252 rightcert=/etc/ipsec.d/certs/myvpn.pem rightprotoport=17/1701 $ ipsec auto –up L2TP-X.509-client [lac ISA] lns = 192.168.0.99 local ip = 192.168.0.169 autodial = yes redial = yes redial timeout = 1 require authentication = no ppp debug = no pppoptfile = /etc/ppp/options.l2tpd.lac $ cat /etc/ppp/options.l2tpd.lac lock noauth nobsdcomp nodeflate noaccomp refuse-eap refuse-pap refuse-chap nomppe mru 1500 mtu 1500 nopersist maxfail 0 defaultroute name filial-1 filial-1 * "000000" * $ sudo /etc/init.d/xl2tpd stop $ sudo /etc/init.d/xl2tpd start $ sudo update-rc.d -f ipsec remove $ sudo update-rc.d ipsec defaults 41 34 [global] listen-addr 192.168.21.99 $ ifconfig eth1 mtu 1440 ----------------------------------------------------------------------------------------------------------------- Обзор SSH-клиентов для Windows Рашид Ачилов --- termcap.new Mon May 12 16:34:10 2003 +++ termcap Mon May 12 19:15:09 2003 @@ -299,7 +299,12 @@ adm3|3|lsi adm3:\ :do=^J:am:le=^H:bs:cl=^Z:li#24:ma=^K^P:co#80: xterm|xterm-color|X11 terminal emulator:\ - :ti@:te@:tc=xterm-xfree86: + :ti@:te@:\ + :ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||:\ + :tc=xterm-xfree86: +xterm-win|X11 terminal emulator cleint:\ + :kh=\E[1~:@7=\E[4~:\ :tc=xterm: ----------------------------------------------------------------------------------------------------------------- Проект RapidDisk Игорь Штомпель blk_queue_ordered(rxdsk->rxdsk_queue, QUEUE_ORDERED_TAG, NULL); blk_queue_flush(rxdsk->rxdsk_queue, REQ_FLUSH); $ sudo apt-get install git $ git clone http://git.petroskoutoupis.com/rxdsk-1.2b.git $ cd rxdsk-1.2b $ make $ sudo make install $ cd module/drivers/block $ make $ sudo insmod rxdsk.ko $ sudo rxadm --attach 512 $ sudo rxadm --list $ sudo rxadm --detach rxd0 $ rxadm --resize rxd0 128 $ rxadm --resize rxd0 1024 $ echo "rxdsk attach 0 512000" > /proc/rxctl $ echo "rxdsk detach 0" > /proc/rxctl $ echo "rxdsk resize 0 1024000" $ cat /proc/filesystems $ uname -srv $ df -H $ sudo mkswap -c /dev/rxd0 $ sudo swapon /dev/rxd0 ----------------------------------------------------------------------------------------------------------------- Веб-разработка с ароматом кофе Валентин Синицын for x in [1..10] … d for d in [2..Math.ceil Math.sqrt n] when n % d == 0 y = (x) -> x*x console.log y 2 app.get url, (req, resp) -> resp.render … app.get(url, function(req, resp) { return resp.render(…); }); npm install coffee-script export PATH=$(pwd)/node_modules/.bin:$PATH coffee -c file.coffee создает file.js coffee -w file.coffee express = require 'express' io = require 'socket.io' fs = require 'fs' tty = require 'tty' auth = require './auth' userStore = require './userstore' app = module.exports = express.createServer { key: fs.readFileSync('vt100-key.pem'), cert: fs.readFileSync 'vt100-cert.pem' } MemoryStore = express.session.MemoryStore sessionStore = new MemoryStore … # Configuration COOKIE_NAME = 'vt100.sid' PORT = process.env.port ? 8000 app.configure -> app.set 'views', __dirname + '/views' app.set 'view engine', 'jade' app.use express.bodyParser() ... restricted = auth.requestAuthentication 'Please authenticate', (req, resp) -> return req.session?.authenticated return req.session && req.session.authenticated; io .configure('development', function () { }) io .configure 'development', -> return (function () { … }).call(this) app.post '/login.html', (req, resp) -> user = userStore.getUser req.body.username, req.body.password if user req.session.authenticated = yes req.session.user = user resp.redirect '/terminal.html' … md5 = require 'crypto/md5' exports.getUser = (login, password) -> userDb[login] if login != '' and userDb[login] and userDb[login]._pw_hash == md5.hex_md5(password) userDb = 'val': userName: 'val', fullName: 'Valentine Sinitsyn', shell: '/bin/bash', _pw_hash: '8fe4c11451281c094a6578e6ddbf5eed', class NotAuthenticated extends Error constructor: (@msg) -> super msg … function NotAuthenticated(msg) { this.msg = msg; NotAuthenticated.__super__.constructor.call(this, msg); } exports.requestAuthentication = (msg, callback) -> return (req, resp, next) -> if callback req, resp next() else throw new NotAuthenticated msg exports.anonymousRedirect = (url) -> return (err, req, res, next) -> if err instanceof NotAuthenticated res.redirect url else next err coffee -c *.coffee window.start = () -> l = document.location socket = window.socket = io.connect l.protocol + "//" + l.host … window.leave = () -> if (socket = window.socket)? … var socket; if ((socket = window.socket) != null) coffee -c terminal.coffee app.use express.compiler { src: __dirname + '/public', enable: ['coffeescript'] } … app.use express.static __dirname + '/public' h1 @title if @messages and @messages != '' div '#messages', -> @messages form '.login', method: 'post', -> div -> label for: 'username', -> 'Username: ' input type: 'text', name: 'username' … p -> text "Welcome to #{@title}. Click here to "; a href:'/login.html', -> 'Log In' text '.' require('coffee-script'); module.exports = require('./app'); node index.js require.extensions['.coffee'] = function(module, filename) { var content; content = compile(fs.readFileSync(filename, 'utf8'), { filename: filename }); return module._compile(content, filename); }; { "name": "vt100" , "version": "3.0.0" , "private": true , "engines": { "node": "~0.4.12" } , "dependencies": { "express": "2.4.7" , "connect": "1.7.1" , "socket.io": "0.8.4" , "crypto": ">= 0.0.1" , "coffee-script": "1.1.3" , "coffeekup": "0.3.1" } , "scripts": {"start": "node index.js"} } ----------------------------------------------------------------------------------------------------------------- ООП в PHP на практике Антон Околелов // Класс, который что-то делает и при этом умеет писать в лог разных типов class ProcessSomething { private $logType; public function __construct( $logType) { $this->logType = $logType; } public function process() { // Делаем что-нибудь полезное // …. $this->log($str); // Еще что-нибудь делаем // …. } private function log($str){ $fp = fopen(“log”, “a”); if ($this->logType == ‘txt’) fwrite($fp. $str); elseif ($this->logType == ‘html’) fwrite($fp, “

$str

”); fclose($fp); } } $ps = new ProcessSomething(‘txt’); $ps->process(); interface LogWriter { function write(); } class TxtLogWriter implements LogWriter { public function write($str){ $fp = fopen(“log”, “a”); fwrite($fp, $str); fclose($fp); } } class ProcessSomething { private $logWriter; public function __construct( LogWriter $logWriter) { $this->logWriter = $logWriter; } public function process() { // Делаем что-нибудь полезное // …. $this->logWriter->write($str); // Еще что-нибудь делаем // …. } } $ps = new ProcessSomething(new TxtLogWriter()); $ps->process(); class DbTable { protected $tableName; protected $db; public function __construct($tableName) { $this->tableName = $tableName; $this->db = Registry::get(‘db’); } public function getCount() { $count = $this->db->fetchOne(‘SELECT count(*) FROM $this->tableName‘); } } class UsersTable extends DbTable { public function __construct() { parent::__construct(“users”); } public function getUserName($id) { $this->db->fetchOne(‘SELECT name FROM $this->tableName WHERE id=?‘, $id); } } class ExtendedUsersTable extends UsersTable { public function __construct(){ // Здесь я не могу просто вызвать // parent::__construct(“extendedusers”); // придется придумывать какой-нибудь «костыль» } } class DbTable { protected $tableName; protected $db; public function __construct() { $this->db = Registry::get(‘db’); } public function getCount() { $count = $this->db->fetchOne(‘SELECT count() FROM $this->tableName‘); } } class UsersTable extends DbTable { protected $tableName = ‘users’; public function getUserName($id) { $this->db->fetchOne(‘SELECT name FROM $this->tableName WHERE id=?‘, $id); } } class ExternalUsersTable extends UsersTable { protected $tableName = ‘extendedusers’; } { private $user; public function __construct (Kernel $kernel) { $this->user = $kernel->getCurrentUser();; } } class ModuleX { private $user public function __construct (User $user) { $this->user = $user; } } class Comment { public function __construct(ArticleModule $articleModule){ ... } $user = User::factory($user_id); $userFactory->createUser($user_id); Registry::get(‘db’); ----------------------------------------------------------------------------------------------------------------- Практика Scapy. Активная диагностика приложений протокола DHCP Андрей Бражук Листинг 1. Фрагмент файла конфигурации сервера ISC DHCP subnet 192.168.56.0 netmask 255.255.255.0 { range 192.168.56.10 192.168.56.30; option domain-name-servers 192.168.56.1; option domain-name "local.test"; option routers 192.168.56.1; option broadcast-address 192.168.56.255; default-lease-time 600; max-lease-time 7200; } >>> fam,hw = get_if_raw_hwaddr("vboxnet0") >>> pktboot = Ether(src=hw, dst="ff:ff:ff:ff:ff:ff")/IP(src="0.0.0.0", dst="255.255.255.255")/UDP(sport=68, dport=67)/BOOTP(chaddr=hw) >>> conf.checkIPaddr = False >>> pktoff = srp1(pktboot/DHCP(options=[("message-type","discover"),"end"]), timeout=2,iface="vboxnet0") >>> print "op =", pktoff[BOOTP].op, ", yiaddr =", pktoff[BOOTP].yiaddr, ", options=", pktoff[DHCP].options >>> pktask = srp1(pktboot/DHCP(options=[("message-type", "request"),("server_id", "192.168.56.2"), ("requested_addr","192.168.56.10"),"end"]), timeout=2,iface="vboxnet0") >>> print pktask[DHCP].options Листинг 2. Простой скрипт, имитирующий DHCP-клиента #!/usr/bin/python from scapy.all import * # search in lst val for fld def getval(lst,fld): for p in lst: if type(p) is tuple: if p[0]==fld: return p[1] return None # err and exit def exterr(msg): print msg sys.exit(1) #main import sys #check args if len(sys.argv) != 2: exterr("Usage: "+sys.argv[0]+" ") myif=sys.argv[1] #mk pktboot conf.checkIPaddr = False fam,hw = get_if_raw_hwaddr(myif) pktboot = Ether(src=hw, dst="ff:ff:ff:ff:ff:ff")/IP(src="0.0.0.0", dst="255.255.255.255")/UDP(sport=68, dport=67)/BOOTP(chaddr=hw) #mk discovery dhdisc = DHCP(options=[("message-type","discover"),"end"]) pktoff = srp1(pktboot/dhdisc, timeout=2,iface=myif) if pktoff != None: if getval(pktoff[DHCP].options,'message-type')==2 and getval(pktoff[DHCP].options,'server_id')!=None and pktoff[BOOTP].yiaddr!=None: print "got OFFER from ",pktoff[IP].src,"(",pktoff[Ether].src,") addr: ",pktoff[BOOTP].yiaddr print pktoff[DHCP].options,"\n" #mk request dhreq = DHCP(options=[("message-type","request"),("server_id",getval(pktoff[DHCP].options,'server_id')),("requested_addr",pktoff[BOOTP].yiaddr),"end"]) pktask = srp1(pktboot/dhreq, timeout=2,iface=myif) if pktask != None: if getval(pktask[DHCP].options,'message-type')==5: print "got ASK from ",pktask[IP].src,"(",pktask[Ether].src,") addr: ",pktask[BOOTP].yiaddr print pktask[DHCP].options # exit ok sys.exit(0) exterr("invalid ACK from server") exterr("no ACK from server") exterr("invalid offer") exterr("no OFFER from server") ans, uans= srp(pktboot/dhdisc, timeout=5,iface=myif, multi=True) for p in ans: print p[1][Ether].src, p[1][IP].src Листинг 3. Фрагмент конфигурации опции 82 в сервере ISC DHCP class "sw1p5" { match if ( (binary-to-ascii (16, 8, ":", option agent.remote-id) = "11:22:33:44:55:66") and (binary-to-ascii (10, 8, "", suffix( option agent.circuit-id, 1)) = "5") ); } pool { allow members of "sw1p5"; range 192.168.56.65 192.168.56.126; } pool { deny members of "sw1p5"; range 192.168.56.10 192.168.56.30; } p="\x01\x01\x05\x02\x06\x11\x22\x34\x44\x55\x66" dhdisc = DHCP(options=[("message-type","discover"),("relay_agent_Information",p),"end"]) ----------------------------------------------------------------------------------------------------------------- Безопасность и аудит. Программное окружение MySQL. Часть 3 Игорь Савчук root@mysql-5.5.17> GRANT ALL PRIVILEGES ON consumer.* TO 'super_usr'@'localhost'; root@mysql-5.5.17> SHOW GRANTS FOR 'super_usr'@'localhost'; root@mysql-5.5.17> GRANT EXECUTE, INSERT, SELECT, UPDATE ON `consumer`.* TO 'usual_usr'@'localhost'; root@mysql-5.5.17> SHOW GRANTS FOR 'usual_usr'@'localhost'; root@mysql-5.5.17> GRANT INSERT, UPDATE ON consumer.City TO 'alaura'@'localhost'; root@mysql-5.5.17> GRANT SELECT ON consumer.City TO 'alaura'@'localhost' WITH GRANT OPTION; root@mysql-5.5.17> SHOW GRANTS FOR 'alaura'@'localhost'; $ sudo mysql_secure_installation oak-security-audit --audit-level=strict oak-security-audit --defaults-file=/home/myuser/ .my-oak.cnf -l normal oak-block-account --block --aсcount--defaults-file=nt-user=mag --account-host=samag.ru oak-block-account --release --account-user=mag --account-host=samag.ru oak-block-account --block --account-user=mag --kill mysql> call block_user ('savgor'); mysql> show processlist; mysql> call unblock_user ('savgor'); [savgor@corelink ~ 19:08:21]$ mysql -u savgor -p -h 127.0.0.1 -P 3306 mysql> show databases; mysql> use securich; mysql> call my_privileges('test'); mysql> call create_update_role('add','role1','insert'); mysql> call revoke_privileges('peter' , 'localhost' , 'test' , '' , '' , 'role1' , 'Y'); mysql> call set_password('paul' , '10.0.0.2' , '2f791928c4ef44ddd7c', 'password123'); root@savgor: /pentest/dbases/mysqlaudit# ./mysqlaudit.py 192.168.2.77 root r00t /tmp/audit-report.txt root@savgor: /pentest/dbases/mysqlaudit# cat /tmp/audit-report.txt | less -----------------------------------------------------------------------------------------------------------------