PROJET AUTOBLOG


Planet-Libre

source: Planet-Libre

⇐ retour index

Francois Aichelbaum : Création d’une plateforme (S) FTP (S) sécurisée avec authentification centralisée et utilisant divers stockages

mercredi 26 septembre 2012 à 17:02

FTPIl y a quelques années, pour l’un de mes employeurs (un gros CDN français pour ne pas le cité), une problématique c’est posée suite à une utilisation abusive des plateformes FTP. En l’occurrence, il y avait plusieurs serveurs FTP :

Suite à l’utilisation abusive de la plateforme (historique) et l’impossibilité de remonter les traces, il a été demandé de sécuriser l’ensemble. J’en ai profité pour faire pas mal de modifications :

J’avais nommé ce genre de plate-forme FTPx. Je cherchais un nouveau sujet de billet. Je me suis dis que j’allais dépoussiérer cette plateforme (la refaire pour le billet donc) en lui rajoutant une petite couche complémentaire (portsentry, honeypot, …).

Avant propos sur la plateforme FTP

L’architecture va se baser exclusivement sur du gratuit. Du coup, je remplace l’Active Directory par un plus basique MySQL. La plateforme montée rapidement se base sur les machines suivantes :

Bien sûr, on pourrait redondé la partie fw ou mysql mais ce n’est pas le sujet de ce billet (je pourrais toujours rédiger un billet dédié s’il y a de la demande pour). Au niveau accès, de l’extérieur, un utilisateur qui fait du SFTP ne pourra pas faire de SSH. De plus, il sera restreint à son arborescence et ne pourra remonté ailleurs.

Schéma architecture FTPX

Au niveau NAS, je ne ferais que la partie cliente, de manière rapide pour montrer la logique. Donc un serveur NFS et un serveur CIFS sont supposés exister.

On suppose à chaque fois partir d’une Debian légère et plutôt vierge. On ignore l’installation du serveur MySQL qui n’a rien de bien particulier.

Au niveau réseau, on notera les réseaux ainsi :

Du coup, on se retrouve avec le plan d’adressage suivant :

Création de fw

On commence par installer les premiers packages.

apt-get -y install bind9 libnetfilter-conntrack3 ldirectord apticron ntp iptables module-assistant xtables-addons-common honeyd fail2ban portsentry

On implémente le module complémentaire d’iptables.

module-assistant --verbose --text-mode auto-install xtables-addons

Serveur DNS récursif

On s’installe un serveur DNS récursif en local pour diverses raisons (dont des histoires de performance).

cat << EOF > /etc/bind/named.conf.options
options {
 directory "/var/cache/bind";
 query-source address * port *;
 forwarders { 208.67.222.222; 208.67.220.220; };
 auth-nxdomain no; # conform to RFC1035
 listen-on-v6 { none; };
 listen-on { 127.0.0.1; };
 allow-transfer { none; };
 allow-query { any; };
 allow-recursion { any; };
 version none;
};
EOF
/etc/init.d/bind9 restart
echo "nameserver 127.0.0.1" > /etc/resolv.conf

Optimisations système

On s’applique à faire quelques optimisations qui seront bien pratique pour la suite.

cat << EOF > /etc/security/limits.conf
* - nofile 65536
EOF
cat << EOF >> /etc/profile
ulimit -n 65536
EOF
cat << EOF > /etc/sysctl.conf
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.arp_filter = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.arp_filter = 1
net.core.rmem_default = 4194304
net.core.rmem_max = 4194304
net.core.wmem_default = 4194304
net.core.wmem_max = 4194304
net.ipv4.tcp_rmem = 4096 87380 4194304
net.ipv4.tcp_wmem = 4096 65536 4194304
net.ipv4.tcp_mem = 4096 65536 4194304
net.ipv4.tcp_low_latency = 0
net.core.netdev_max_backlog = 30000
fs.file-max = 65536
kernel.shmmax = 8000000000
kernel.shmall = 8000000000
net.ipv4.tcp_abort_on_overflow = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_fin_timeout = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 1024 65535
vm.min_free_kbytes = 65536
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.eth0.arp_ignore = 1
net.ipv4.conf.eth1.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.eth0.arp_announce = 2
net.ipv4.conf.eth1.arp_announce = 2
net.ipv4.tcp_orphan_retries = 0
net.ipv4.tcp_timestamps = 0 
net.ipv4.tcp_sack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_keepalive_intvl = 1
net.ipv4.tcp_keepalive_probes = 1 
net.ipv4.ip_forward = 1
net.ipv4.conf.default.proxy_arp = 1
net.ipv4.conf.all.proxy_arp = 1
kernel.sysrq = 1
net.ipv4.conf.default.send_redirects = 1
net.ipv4.conf.all.send_redirects = 1
kernel.core_uses_pid=1
kernel.core_pattern=1
vm.dirty_background_ratio = 20
vm.dirty_ratio = 40
vm.swappiness = 1
vm.dirty_writeback_centisecs = 1500
net.ipv4.tcp_max_syn_backlog = 65536
net.core.optmem_max = 40960
net.ipv4.tcp_max_tw_buckets = 360000
net.ipv4.tcp_reordering = 5
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_rfc1337 = 0
net.core.somaxconn=65536
net.ipv4.tcp_moderate_rcvbuf=1
net.ipv4.tcp_ecn=0
net.ipv4.ip_no_pmtu_disc=0
net.ipv4.tcp_slow_start_after_idle=0
net.netfilter.nf_conntrack_acct=1
net.ipv4.icmp_echo_ignore_broadcasts=1
EOF
sysctl -p

Fail2ban & honeypot

L’idée est d’utiliser le honeypot pour bannir les mauvaises personnes. Pour se faire, vu qu’on doit appliquer les règles au niveau de fw, aussi bien pour du INPUT que du FORWARD et sur plusieurs IP, on va le faire via fail2ban.

cat << EOF > /etc/rc.local
farpd x.x.x.2 -i eth0
/usr/local/bin/rules.sh start 
exit 0
EOF

farpd x.x.x.2 -i eth0
wget http://www.alunos.di.uminho.pt/~a43175/code/perl/customPie.pm -O /etc/honeypot/customPie.pm
wget http://www.alunos.di.uminho.pt/~a43175/code/perl/buildPie.pl -O /etc/honeypot/buildPie.pl
cat << EOF > /etc/default/honeyd
RUN="yes"
INTERFACE="eth0"
NETWORK=x.x.x.2
OPTIONS="--disable-webserver"
EOF

cat << EOF > /etc/honeypot/honeyd.conf
create win2k
set win2k personality "Microsoft Windows 2000 SP2"
set win2k default tcp action block
set win2k default udp action block
set win2k default icmp action block
set win2k uptime 3567
set win2k droprate in 13
add win2k tcp port 23 "sh /usr/share/honeyd/scripts/unix/linux/suse8.0/telnetd.sh $ipsrc $sport $ipdst $dport"
add win2k tcp port 21 "sh /usr/share/honeyd/scripts/win32/win2k/msftp.sh $ipsrc $sport $ipdst $dport"
add win2k tcp port 25 "sh /usr/share/honeyd/scripts/win32/win2k/exchange-smtp.sh $ipsrc $sport $ipdst $dport"
#add win2k tcp port 80 "sh /usr/share/honeyd/scripts/win32/win2k/iis.sh $ipsrc $sport $ipdst $dport"
add win2k tcp port 110 "sh /usr/share/honeyd/scripts/win32/win2k/exchange-pop3.sh $ipsrc $sport $ipdst $dport"
add win2k tcp port 143 "sh /usr/share/honeyd/scripts/win32/win2k/exchange-imap.sh $ipsrc $sport $ipdst $dport"
add win2k tcp port 389 "sh /usr/share/honeyd/scripts/win32/win2k/ldap.sh $ipsrc $sport $ipdst $dport"
add win2k tcp port 5901 "sh /usr/share/honeyd/scripts/win32/win2k/vnc.sh $ipsrc $sport $ipdst $dport"
add win2k udp port 161 "perl /usr/share/honeyd/scripts/unix/general/snmp/fake-snmp.pl public private --config=/usr/share/honeyd/scripts/unix/general/snmp"
# This will redirect incomming windows-filesharing back to the source
add win2k udp port 137 proxy $ipsrc:137
add win2k udp port 138 proxy $ipsrc:138
add win2k udp port 445 proxy $ipsrc:445
add win2k tcp port 137 proxy $ipsrc:137
add win2k tcp port 138 proxy $ipsrc:138
add win2k tcp port 139 proxy $ipsrc:139
add win2k tcp port 445 proxy $ipsrc:445
bind x.x.x.2 win2k
EOF

/etc/init.d/honeyd restart

cat << EOF > /etc/fail2ban/filter.d/honeyd.conf
[Definition]
failregex = .* S  .*$
ignoreregex = 
EOF

cat << EOF > /etc/fail2ban/action.d/banhost.conf
[Definition]
actionstart = 
actionstop = 
actioncheck = 
actionban = /usr/local/bin/banip.sh 
actionunban = /usr/local/bin/unbanip.sh 
EOF

cat << EOF > /etc/fail2ban/jail.conf
[DEFAULT]
ignoreip = 127.0.0.1 x.x.x.1
bantime = 86400
maxretry = 3
backend = polling
destemail = root@localhost
banaction = iptables-multiport
mta = sendmail
protocol = tcp
action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s]
action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s]
 %(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s]
action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s]
 %(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s]

action = %(action_)s
[ssh]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 6
[honeyd]
enabled = trueinitctl list
filter = honeyd
port = all
logpath = /var/log/honeypot/honeyd.log
maxretry = 1
banaction = banhost
EOF

/etc/init.d/fail2ban restart

Toute personne tentant d’ouvrir un port sur l’honeypot sera automatiquement banni de la plateforme à coup de TARPIT pour la partie TCP et de DROP pour tout le reste.

Portsentry

Comment lutter contre un scan de port ? Grâce à portsentry bien sûr !

cat << EOF > /etc/default/portsentry
TCP_MODE="atcp"
UDP_MODE="audp"
EOF

cat << EOF > /etc/portsentry/portsentry.conf
TCP_PORTS="1,7,9,11,15,20,21,2370,79,109,110,111,119,138,139,143,512,513,514,515,540,635,1080,1524,2000,2001,4000,4001,5742,6000,6001,6667,12345,12346,20034,27665,30303,32771,32772,32773,32774,31337,40421,40425,49724,54320"
UDP_PORTS="1,7,9,66,67,68,69,111,137,138,161,162,474,513,517,518,635,640,641,666,700,2049,31335,27444,34555,32770,32771,32772,32773,32774,31337,54321"
ADVANCED_PORTS_TCP="65536"
ADVANCED_PORTS_UDP="65536"
ADVANCED_EXCLUDE_TCP="80"
ADVANCED_EXCLUDE_UDP=""
IGNORE_FILE="/etc/portsentry/portsentry.ignore"
HISTORY_FILE="/var/lib/portsentry/portsentry.history"
BLOCKED_FILE="/var/lib/portsentry/portsentry.blocked"
RESOLVE_HOST = "0"
BLOCK_UDP="2"
BLOCK_TCP="2"
KILL_ROUTE="/sbin/route add -host $TARGET$ reject"
KILL_HOSTS_DENY="ALL: $TARGET$ : DENY"
KILL_RUN_CMD_FIRST = "0"
KILL_RUN_CMD="/usr/local/bin/banip.sh $TARGET$"
SCAN_TRIGGER="0"
EOF

cat << EOF > /etc/portsentry/portsentry.ignore.static
208.67.222.222
208.67.220.220
x.x.x.254
EOF

Encore une fois, on va utiliser un script qui va nous bannir correctement l’IP sur l’ensemble de la plateforme.

Toute personne tentant un scan de port sera automatiquement banni de la plateforme à coup de TARPIT pour la partie TCP et de DROP pour tout le reste.

Scripting

On va utiliser quelques scripts selon la tâche à exécuter :

cat << EOF > /usr/local/bin/rules.sh
#!/bin/bash

start() {
 echo "Routing"
 iptables -t nat -A POSTROUTING -o eth2 -j MASQUERADE
 iptables -t nat -A PREROUTING -d x.x.x.3 -m tcp -p tcp --dport 21 -j DNAT --to-destination z.z.a.11
 iptables -t nat -A PREROUTING -d x.x.x.3 -m tcp -p tcp --dport 22 -j DNAT --to-destination z.z.a.11
 iptables -t mangle -A PREROUTING -i eth0 -p tcp -s 0.0.0.0/0 -d x.x.x.3/32 --dport ftp -j MARK --set-mark 1
 iptables -t mangle -A PREROUTING -i eth0 -p tcp -s 0.0.0.0/0 -d x.x.x.3/32 --dport 55000: -j MARK --set-mark 1
 for chain in INPUT FORWARD; do
  echo "Block DOS - $chain - Ping of Death"
  iptables -A $chain -p ICMP --icmp-type echo-request -m length --length 60:65535 -j ACCEPT;
  echo "Block DOS - $chain - Teardrop"
  iptables -A $chain -p UDP -f -j DROP;
  echo "Block DDOS - $chain - SYN-flood"
  iptables -A $chain -p TCP ! --syn -m state --state NEW -j TARPIT;
  iptables -A $chain -p TCP ! --syn -m state --state NEW -j DROP;
  echo "Block DDOS - $chain - Smurf"
  iptables -A $chain -m pkttype --pkt-type broadcast -j DROP;
  iptables -A $chain -p ICMP --icmp-type echo-request -m pkttype --pkt-type broadcast -j DROP;
  iptables -A $chain -p ICMP --icmp-type echo-request -m limit --limit 3/s -j ACCEPT;
  echo "Block DDOS - $chain - UDP-flood (Pepsi)"
  iptables -A $chain -p UDP --dport 7 -j DROP;
  iptables -A $chain -p UDP --dport 19 -j DROP;
  echo "Block DDOS - $chain - SMBnuke"
  iptables -A $chain -p UDP --dport 135:139 -j DROP;
  iptables -A $chain -p TCP --dport 135:139 -j TARPIT;
  iptables -A $chain -p TCP --dport 135:139 -j DROP;
  echo "Block DDOS - $chain - Connection-flood"
  iptables -A $chain -p TCP --syn -m connlimit --connlimit-above 3 -j TARPIT;
  iptables -A $chain -p TCP --syn -m connlimit --connlimit-above 3 -j DROP;
  echo "Block DDOS - $chain - Fraggle"
  iptables -A $chain -p UDP -m pkttype --pkt-type broadcast -j DROP;
  iptables -A $chain -p UDP -m limit --limit 3/s -j ACCEPT;
  echo "Block DDOS - $chain - Jolt"
  iptables -A $chain -p ICMP -f -j DROP; 
 done
 /etc/init.d/portsentry start
}
stop() {
 /etc/init.d/portsentry stop
 iptables -F
 iptables -X 
 iptables -F -t nat
 iptables -X -t nat
 iptables -F -t mangle
 iptables -X -t mangle
}
case "$1" in
 start)
  start
  ;;
 stop)
  stop
  ;;
 restart|reload)
  stop
  start
  ;;
 *)
  echo "$0 "
  exit 1
  ;;
esac
exit 0
EOF

chmod +x /usr/local/bin/rules.sh

cat << EOF > /usr/local/bin/banip.sh
#!/bin/bash
if [ $# -ne 1 ]; then
 echo "usage: $0 IP";
 exit 1;
fi

/sbin/iptables -I INPUT -s $1 -m tcp -p tcp -j TARPIT 
/sbin/iptables -I INPUT -s $1 -j DROP 
/sbin/iptables -I FORWARD -s $1 -m tcp -p tcp -j TARPIT 
/sbin/iptables -I FORWARD -s $1 -j DROP 
/sbin/iptables -I INPUT -s $1 -m limit --limit 1/minute --limit-burst 3 -j LOG --log-level debug --log-prefix 'Portsentry: tarpiting: '
exit 0
EOF

chmod +x /usr/local/bin/banip.sh

cat << EOF > /usr/local/bin/unbanip.sh
#!/bin/bash
if [ $# -ne 1 ]; then
 echo "usage: $0 IP";
 exit 1;
fi
for chain in INPUT FORWARD; do
 for id in `iptables -L $chain -n --line-numbers | grep $1 | awk '{ print $1 }'`; do
  iptables -D $chain $id;
 done
done
exit 0
EOF

chmod +x /usr/local/bin/unbanip.sh

Load balancing

On enchaine avec le load balancing. On déclare l’IP de la VIP en alias.

cat << EOF >> /etc/network/interfaces
auto eth0:0
iface eth0:0 inet static
 address x.x.x.3
 netmask 255.255.255.255
EOF

Puis on configure le load balancing en lui-même. Attention, le serveur FTP va fonctionner en mode passif, donc on prévoir l’ouverture des ports dynamiques et non prévisibles au niveau du load balancing.

echo CONFIG_FILE=/etc/ldirectord.cf >> /etc/default/ldirectord

cat << EOF > /etc/ldirectord.cf
 checktimeout=1
 negotiatetimeout=1
 checkinterval=5
 autoreload=yes
 logfile="l0"
 quiescent=yes
 virtual=1
 real=z.z.a.11 gate
 real=z.z.a.12:21 gate
 service=ftp
 scheduler=lc
 protocol=fwm
 persistent=5
 checktype=negotiate
 virtual=x.x.x.3:22
 real=z.z.a.11:22 gate
 real=z.z.a.12:22 gate
 service=ftp
 scheduler=lc
 protocol=tcp
 persistent=5
 checktype=negotiate
 EOF

/etc/init.d/ldirectord restart

Création d’un serveur ftpx

On commence par installer les premiers packages.

apt-get -y install bind9 iptables fail2ban libpam-mysql mysql-client libnss-mysql-bg nscd pure-ftpd

SERVEUR DNS RÉCURSIF

On s’installe un serveur DNS récursif en local pour diverses raisons (dont des histoires de performance).

cat << EOF > /etc/bind/named.conf.options
options {
 directory "/var/cache/bind";
 query-source address * port *;
 forwarders { 208.67.222.222; 208.67.220.220; };
 auth-nxdomain no; # conform to RFC1035
 listen-on-v6 { none; };
 listen-on { 127.0.0.1; };
 allow-transfer { none; };
 allow-query { any; };
 allow-recursion { any; };
 version none;
};
EOF
/etc/init.d/bind9 restart
echo "nameserver 127.0.0.1" > /etc/resolv.conf

OPTIMISATIONS SYSTÈME

On s’applique à faire quelques optimisations qui seront bien pratique pour la suite.

cat << EOF > /etc/security/limits.conf
* - nofile 65536
EOF
cat << EOF >> /etc/profile
ulimit -n 65536
EOF
cat << EOF > /etc/sysctl.conf
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.arp_filter = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.arp_filter = 1
net.core.rmem_default = 4194304
net.core.rmem_max = 4194304
net.core.wmem_default = 4194304
net.core.wmem_max = 4194304
net.ipv4.tcp_rmem = 4096 87380 4194304
net.ipv4.tcp_wmem = 4096 65536 4194304
net.ipv4.tcp_mem = 4096 65536 4194304
net.ipv4.tcp_low_latency = 0
net.core.netdev_max_backlog = 30000
fs.file-max = 65536
kernel.shmmax = 8000000000
kernel.shmall = 8000000000
net.ipv4.tcp_abort_on_overflow = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_fin_timeout = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 1024 65535
vm.min_free_kbytes = 65536
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.eth0.arp_ignore = 1
net.ipv4.conf.eth1.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.eth0.arp_announce = 2
net.ipv4.conf.eth1.arp_announce = 2
net.ipv4.tcp_orphan_retries = 0
net.ipv4.tcp_timestamps = 0 
net.ipv4.tcp_sack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_keepalive_intvl = 1
net.ipv4.tcp_keepalive_probes = 1 
net.ipv4.ip_forward = 1
net.ipv4.conf.default.proxy_arp = 1
net.ipv4.conf.all.proxy_arp = 1
kernel.sysrq = 1
net.ipv4.conf.default.send_redirects = 1
net.ipv4.conf.all.send_redirects = 1
kernel.core_uses_pid=1
kernel.core_pattern=1
vm.dirty_background_ratio = 20
vm.dirty_ratio = 40
vm.swappiness = 1
vm.dirty_writeback_centisecs = 1500
net.ipv4.tcp_max_syn_backlog = 65536
net.core.optmem_max = 40960
net.ipv4.tcp_max_tw_buckets = 360000
net.ipv4.tcp_reordering = 5
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_rfc1337 = 0
net.core.somaxconn=65536
net.ipv4.tcp_moderate_rcvbuf=1
net.ipv4.tcp_ecn=0
net.ipv4.ip_no_pmtu_disc=0
net.ipv4.tcp_slow_start_after_idle=0
net.netfilter.nf_conntrack_acct=1
net.ipv4.icmp_echo_ignore_broadcasts=1
EOF
sysctl -p

Rajout d’un point d’entrée pour syslog-ng

Pensez simplement à rajouter la ligne suivante dans less sources de syslog-ng (/etc/syslog-ng/syslog-ng.conf) pour logguer tout ce que font vos utilisateurs).

unix-stream("/chroot/log" max-connections(2048));

Configuration de PAM & NSS pour utiliser MySQL

On suppose le serveur MySQL pré-installé. On y configure un compte pour PAM et la table d’utilisateurs qui va bien.

cat << EOF | mysql -u root -h z.z.b.21 -p
CREATE DATABASE pam;
GRANT SELECT ON pam.* TO 'pam'@'%' IDENTIFIED BY 'pampass';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP ON pam.* TO 'pamadm'@'%' IDENTIFIED BY 'pamadmpass';
FLUSH PRIVILEGES;
USE pam;
CREATE TABLE `accounts` (
`id` INT NOT NULL auto_increment primary key,
`username` VARCHAR( 30 ) NOT NULL ,
`login` VARCHAR( 30 ) NOT NULL ,
`pass` VARCHAR( 50 ) NOT NULL ,
UNIQUE (`username`)
) ENGINE = MYISAM ;
quit;
EOF

On poursuit avec la modification de nsswitch.conf. Pour cela on remplace les lignes passwd et shadow (mais pas group) :

passwd:  compat files  mysql 
shadow:  compat files  mysql

Puis on prépare l’accès MySQL de nsswitch.

cat << EOF > /etc/libnss-mysql.cfg
getpwnam SELECT login,'x',id+'2000','2000',username,CONCAT('/opt/ftpx/',login,login),'/bin/false' \\ 
 FROM accounts \\ 
 WHERE login='%1$s' \\ 
 LIMIT 1 
getpwuid SELECT login,'x',id+'2000','2000',username,CONCAT('/opt/ftpx/',login,login),'/bin/false' \\ 
 FROM accounts \\ 
 WHERE id='%1$u'-2000 \\ 
 LIMIT 1 
getspnam SELECT login,pass,'','','','','','','' \\ 
 FROM accounts \\ 
 WHERE login='%1$s' \\ 
 LIMIT 1 
getpwent SELECT login,'x',id+'2000','2000',username,CONCAT('/opt/ftpx/',login,login),'/bin/false' \\ 
 FROM accounts 
getspent SELECT login,pass,'','','','','','','' \\ 
 FROM accounts 
getgrnam SELECT name,password,gid \\ 
 FROM groups \\ 
 WHERE name='%1$s' \\ 
 LIMIT 1 
getgrgid SELECT name,password,gid \\ 
 FROM groups \\
 WHERE gid='%1$u' \\ 
 LIMIT 1 
getgrent SELECT name,password,gid \\ 
 FROM groups 
memsbygid SELECT username \\ 
 FROM grouplist \\ 
 WHERE gid='%1$u' 
gidsbymem SELECT gid \\ 
 FROM grouplist \\ 
 WHERE username='%1$s' 
host z.z.b.21
database pam 
username pam 
password pampass
port 3306
EOF

cat << EOF > /etc/libnss-mysql-root.cfg
host        z.z.b.21 
database    accounts 
username    pamadm
password    pamadmpass
port        3306
EOF

On ne définit en soit que les utilisateurs à qui on n’impose un groupe bien précis ‘sftponly’.

groupadd -g 2000 sftponly

Reste à finir la configuration de PAM.

cat << EOF > /etc/pam_mysql.conf
users.host=z.z.b.21
users.db_user=pamadm
users.db_passwd=pamadmpass
users.database=pam
users.table=accounts 
users.user_column=login 
users.password_column=pass 
users.password_crypt=2
verbose=1
EOF

echo auth   required     pam_mysql.so    config_file=/etc/pam_mysql.conf >> /etc/pam.d/common-auth
echo account required pam_mysql.so config_file=/etc/pam_mysql.conf >> /etc/pam.d/common-account
echo session required pam_mysql.so config_file=/etc/pam_mysql.conf >> /etc/pam.d/common-session 
echo password required pam_mysql.so config_file=/etc/pam_mysql.conf >> /etc/pam.d/common-password

Restrictions pour SSH

Maintenant que l’on peut s’authentifier avec des données en base, il faut restreindre la partie SSH. Le chroot de base ne me convient pas. En effet, il nécessite que le groupe d’utilisateurs ait accès en lecture au dossier parent. Or, je souhaite leur restreindre un maximum la visibilité sur leurs petits voisins. Pour cela, il faut patcher openssh en conséquence.

apt-get source openssh-server
apt-get build-dep openssh-server
cd openssh-5.9p1
cat << EOF > patch.diff
--- session.c.orig 2012-09-26 15:34:02.119243513 +0200
+++ session.c 2012-09-26 15:34:24.951244387 +0200
@@ -1457,7 +1457,7 @@
 if (stat(component, &st) != 0)
 fatal("%s: stat(\\"%s\\"): %s", __func__,
 component, strerror(errno));
- if (st.st_uid != 0 || (st.st_mode & 022) != 0)
+ if (st.st_uid != 0 || (st.st_mode & 077) != 0)
 fatal("bad ownership or modes for chroot "
 "directory %s\\"%s\\"", 
 cp == NULL ? "" : "component ", component);
EOF 
patch < patch.diff 
dpkg-buildpackage -rfakeroot -sa -b
cd ..
dpkg -i openssh-server*deb
rm -fR openssh*

On peut maintenant finaliser la configuration d’openssh.

sed "s^Subsystem sftp /usr/lib/openssh/sftp-server^^" /etc/ssh/sshd_config
mkdir /opt/sftpd
chmod 700 /opt/sftpd
cat << EOF >> /etc/ssh/sshd_config
Subsystem sftp internal-sftp -f AUTH -l VERBOSE
Match Group sftponly
        ChrootDirectory /opt/sftp/%u/%u
        ForceCommand internal-sftp
        AllowTcpForwarding no
        GatewayPorts no
        X11Forwarding no
EOF
/etc/init.d/ssh restart

Mise en place de la partie FTP

On va utiliser pure-ftpd. Pourquoi ? Pour une raison parfaitement objective indépendante de toute pollution extérieure : juste “j’aime bien”. Au delà de ce point, il reste un très bon produit.

cat << EOF > /etc/default/pure-ftpd-common
STANDALONE_OR_INETD=standalone
VIRTUALCHROOT=true
UPLOADUID=
UPLOADGID=
EOF

echo yes > /etc/pure-ftpd/auth/65unix
echo yes > /etc/pure-ftpd/auth/70pam

echo 1 > AllowUserFXP
echo stats:/var/log/pure-ftpd/transfer.log > AltLog
echo 21 > Bind
echo yes > ChrootEveryone
echo 1 > CustomerProof
echo 1 > DisplayDotFiles
echo 1 > DontResolve
echo UTF-8 > FSCharset
echo 100 > MaxClientsNumber
echo 10 > MaxClientsPerIP
echo 99 > MaxDiskUsage
echo 5 > MaxIdleTime
echo 2000 > MinUID
echo yes > NoAnonymous
echo 1 > NoTruncate
echo yes > PAMAuthentication
echo 55000 56000 > PassivePortRange
echo /etc/pure-ftpd/pureftpd.pdb > PureDB
echo ftp > SyslogFacility
echo 1 > TLS
echo 117 007 > Umask
echo yes > UnixAuthentication
echo 1 > VerboseLog

mkdir -p /etc/ssl/private
openssl req -x509 -nodes -newkey rsa:2048 -keyout /etc/ssl/private/pure-ftpd.pem -out /etc/ssl/private/pure-ftpd.pem
chmod 600 /etc/ssl/private/pure-ftpd.pem

/etc/init.d/pure-ftpd restart

Montage des arborescences réelles et virtuelles

Comme à l’habitude, vous monter vos différents points d’accès NFS et CIFS. On suppose qu’il s’agit de sous dossier de /mnt.

cat << EOF > /etc/init.d/masquerade
#!/bin/sh
case "$1" in
start)
 echo "Start 'masquarade'..."
 echo " mount remote fs"
 mount -t cifs -a
 mount -t nfs -a
 echo " enslave remote fs"
 mount --make-slave /mnt/cifs01
 mount --make-slave /mnt/cifs02
 mount --make-slave /mnt/cifs03
 mount --make-slave /mnt/nfs01
 mount --make-slave /mnt/nfs02
 mount --make-slave /mnt/nfs03
 echo " bind user mounts/chroot"
 /usr/local/bin/masquarade.sh add > /var/log/masquarade.log 2> /var/log/masquarade.err
 [ $? -ne 0 ] && echo " failed to bind all users mounts/chroots."
 ;;
stop)
 echo "Stop 'masquarade'..."
 echo " unbind users mounts/chroot" 
 /usr/local/bin/masquarade.sh del > /var/log/masquarade.log 2> /var/log/masquarade.err
 [ $? -ne 0 ] && echo " failed to unbind all users mounts/chroots."
 echo " free remote fs"
 umount /mnt/cifs01
 umount /mnt/cifs02
 umount /mnt/cifs03
 umount /mnt/nfs01
 umount /mnt/nfs02
 umount /mnt/nfs03
 ;;
restart)
 $0 stop
 sleep 5
 $0 start
 ;;
reload)
 $0 restart
 ;;
force-reload)
 $0 restart
 ;;
*)
 echo "Usage: $0 {start|stop|restart|force-reload}" >&2
 exit 3
 ;;
esac
exit 0
EOF
chmod +x /etc/init.d/masquerade
update-rc.d masquerade defaults

cat << EOF > /usr/local/bin/masquarade.sh
#!/bin/bash
CONF="/usr/local/etc/mounts"
DATE=`date +%s`
# USAGE
function usage()
{
 echo "Usage: $0   [[] ...]";
 echo " add - to add one or several mount";
 echo " del - to remove one or several mount";
 echo " mount - mount name from config file";
 echo " help - this usage";
 echo "";
 echo "If no mount point is provided, all mount points from config file will be treated";
 echo "Configuration: $CONF";
 echo "";
}
# ADD A PMOUNT POINT
function addMount()
{
 touch /tmp/masquarade.$DATE
 if [ $# -ne 0 ]
 then
 echo "[ Traitement de points particuliers ]"
 echo " Preparation du listing: "
 for point in $*
 do
 if [ `grep -ve '^#' $CONF | grep -ve '^\\s*$' | grep -F $point | wc -l` -eq 0 ]
 then
 echo " Aucun point $PBIND existant dans la configuration"
 continue
 fi
 grep -ve '^#' $CONF | grep -ve '^\\s*$' | grep -F $point >> /tmp/masquarade.$DATE
 done
 else
 echo "[ Utilisation du fichier complet ]"
 echo " Preparation du listing: "
 grep -ve '^#' $CONF | grep -ve '^\\s*$' >> /tmp/masquarade.$DATE
 fi
 cat /tmp/masquarade.$DATE | while read line
 do
 # extract data for mount point
 PTYPE=`echo $line | awk -F';' '{ print $1 }'` # NOT USED
 PMOUNT=`echo $line | awk -F';' '{ print $3 }'`
 PBIND=`echo $line | awk -F';' '{ print $2 }'`
 PRIGHTS=`echo $line | awk -F';' '{ print $4 }'`
 echo -n "( + ) $PBIND: "
 # check the source
 if [ ! -d $PMOUNT ]
 then
 echo "$PMOUNT n'existe pas";
 continue
 fi
 # create the binding
 mkdir -p $PBIND
 #echo "mount -vvv -o bind $PMOUNT $PBIND" &> /tmp/pouet.log; 
 #mount -vvv -o bind $PMOUNT $PBIND &>> /tmp/pouet.log; 
 mount -o bind $PMOUNT $PBIND 2> /dev/null;
 if [ $? -ne 0 ]
 then
 echo " impossible de monter $PBIND"
 continue
 fi
 if [ $PRIGHTS == "ro" ]
 then
 mount -o remount,ro $PBIND 2> /dev/null
 if [ $? -ne 0 ]
 then
 echo " impossible de passer $PBIND en lecture seule"
 continue
 fi
 fi
 echo -n "$PBIND mounted ($PRIGHTS) "
 echo "ok"
 done
 if [ $# -ne 0 ]
 then
 for point in $*
 do
 account=${point#/opt/sftp/}
 account=${account%/*}
 echo -n "* $account: "
 if [ `mount | grep -F /opt/sftp/$account/dev | wc -l` -gt 0 ]
 then
 echo "already exists"
 else
 mkdir -p /opt/sftp/$account/$account/dev/ 2> /dev/null
 mount -o bind /chroot/ /opt/sftp/$account/$account/dev/ 2> /dev/null
 chmod 700 /opt/sftp/$account 2> /dev/null
 chown root:root /opt/sftp/$account 2> /dev/null
 chmod 500 /opt/sftp/$account/$account/dev 2> /dev/null
 fi
 echo "ok"
 done
 else
 for account in `ls /opt/sftp`; do
 echo -n "* $account: "
 if [ `mount | grep -F /opt/sftp/$account/$account/dev | wc -l` -gt 0 ]
 then
 echo "already exists"
 else
 mkdir -p /opt/sftp/$account/$account/dev/ 2> /dev/null
 mount -o bind /chroot/ /opt/sftp/$account/$account/dev/ 2> /dev/null
 chmod 700 /opt/sftp/$account 2> /dev/null
 chown root:root /opt/sftp/$account 2> /dev/null
 chmod 500 /opt/sftp/$account/$account/dev 2> /dev/null
 fi
 echo "ok"
 done
 fi
 rm -f /tmp/masquarade.$DATE
 return
}
# DELETE A PMOUNT POINT
function delMount()
{
 if [ $# -ne 0 ]
 then
 echo "[ Traitement de points particuliers ]"
 echo " Preparation du listing: "
 for point in $*
 do
 if [ `grep -ve '^#' $CONF | grep -ve '^\\s*$' | grep -F $point | wc -l` -eq 0 ]
 then
 echo " Aucun point $PBIND existant dans la configuration"
 continue
 fi
 grep -ve '^#' $CONF | grep -ve '^\\s*$' | grep -F $point >> /tmp/masquarade.$DATE
 done
 else
 echo "[ Utilisation du fichier complet ]"
 echo " Preparation du listing: " 
 grep -ve '^#' $CONF | grep -ve '^\\s*$' >> /tmp/masquarade.$DATE
 echo " Retrait des logs"
 for account in `ls /opt/sftp`
 do
 umount -f /opt/sftp/$account/$account/dev/ 2> /dev/null
 #rmdir /opt/sftp/$account/$account/dev/ 2> /dev/null
 done
 fi
 tac /tmp/masquarade.$DATE | while read line
 do
 PBIND=`echo $line | awk -F';' '{ print $2 }'`
 PRIGHTS=`echo $line | awk -F';' '{ print $4 }'`
 echo -n "( - ) $PBIND: "
 if [ `grep $PBIND /proc/mounts | grep -v grep | wc -l` -eq 0 ]
 then
 echo "$PBIND n'est pas/plus monte"
 else
 umount -f $PBIND 2> /dev/null
 if [ $? -ne 0 ]
 then
 echo "Impossible de demonter $PBIND"
 continue
 fi
 fi
 echo "ok"
 done
 rm /tmp/masquarade.$DATE
}
if [ $# -eq 0 ]
then
 usage
 exit 0
fi
if [ ! -f $CONF ]
then
 echo "Fichier $CONF manquant !"
 echo "Syntaxe du fichier: PTYPE;PMOUNT;PBIND;PRIGHTS"
 exit 1
fi
action=0;
pos=0;
points="";
for arg in `echo $*`; do
 ((pos++))
 case "$arg" in
 help)
 usage;
 exit 0;
 ;;
 add)
 action=1;
 if [ $# -eq 1 ]; then
 addMount;
 fi
 ;;
 del)
 action=-1;
 if [ $# -eq 1 ]; then
 delMount;
 fi
 ;;
 *)
 points="${points} $arg";
 if [ $pos -eq $# ]; then
 if [ $action -eq 0 ]; then
 usage;
 exit 0;
 else if [ $action -gt 0 ]; then
 addMount $points;
 else 
 delMount $points;
 fi
 fi
 exit 0;
 fi
 ;;
 esac
done
exit 0
EOF 
chmod +x /usr/local/bin/masquarade.sh

/etc/init.d/masquerade start

L’idée est que chaque utilisateur est isolé et chrooté dans son coin. Il ne remonte pas l’arborescence et n’a même pas les droits en lecture chez ses voisins. De plus, chaque action peut être loguée puisque transmise à syslog-ng.

VIP

Pour que le load balancing fonctionne avec la bonne IP dans le paquet réseau, on pense à définir un alias.

cat << EOF >> /etc/network/interfaces
auto lo:0
iface lo:0 inet static
 address x.x.x.3
 netmask 255.255.255.255
EOF

Création d’un utilisateur

Avec votre client MySQL préféré (CLI, phpMyAdmin, autre…), il vous suffit alors de rajouter une entrée en respectant les points suivants :

Conclusion

Avec cette base de plateforme, vous avez de quoi avoir un dépôt de fichiers multi utilisateur en FTP (avec ou sans SSL) et en SFTP avec un seule et unique point d’authentification, et pas mal de sécurisation au niveau des accès et remontées d’arborescence. Si vous avez des questions ou remarque, comme à l’habitude, n’hésitez pas.

Merci à Guillaume Vaillant qui m’a ressorti mes archives.

The post Création d’une plateforme (S) FTP (S) sécurisée avec authentification centralisée et utilisant divers stockages appeared first on D'ici et d'ailleurs.

Gravatar de Francois Aichelbaum
Original post of Francois Aichelbaum.Votez pour ce billet sur Planet Libre.

Nÿco : News XMPP : Openfire, Psi, Hermes, Perl Ocean

mercredi 26 septembre 2012 à 15:40

Quelques news XMPP du moment.

Openfire en cluster avec Hazelcast

Le communauté Openfire a dévelopé un module permettant de clusteriser PubSub. Avant, le clusterting reposait sur Oracle Coherence, mais désormais il repose sur Hazelcast (Community Edition, sous licence Apache 2.0). C’est encore à ce jour dans le dépôt… SVN, hum. Mais à suivre donc, notamment la prochaine version.

Psi 0.15 RC 3

Pendant ce temps, Psi fait son chemin, et c’est une RC3 qui est publiée. La vraie version 0.15 sera publiée le 3 octobre.

Des chatrooms pour tous avec Hermes

Hermes est un serveur de chatrooms développé en Python. Ce n’est pas un composant XMPP, ça ne sert pas des MUC, mais cela permet, une fois connecté à un compte, de jouer le rôle de proxy pour relayer les messages entre tous les participants. La chatroom hébergé sur un JID est protégée par mot de passe et les fonctionnalités sont limitées : mute/unmute, invite/kick, et marco/polo pour voir son état dans la chatroom. Il est prévu que la persistance soit développée.

Perl Ocean

Perl Ocean est un framework de communication temps-réel basé sur XMPP, un article le présente plus en détail. Si vous ne maîtriser pas le japonais, je ne saurais torp vous conseiller un traducteur automatique.


Gravatar de Nÿco
Original post of Nÿco.Votez pour ce billet sur Planet Libre.

Articles similaires

Framablog : Quand Linus Torvalds se lâche sur Linux et Git

mercredi 26 septembre 2012 à 15:20

Vous prenez tranquillement un café à Portland, dans l’Oregon, lorsque tout d’un coup vous vous apercevez que c’est Linus Torvalds en personne qui se trouve à la table d’à côté.

Comme vous êtes 1. développeur et 2. pas timide, vous l’accostez gentiment et lui demandez s’il accepterait de répondre à quelques questions.

Et l’on découvre alors un Torvalds toujours aussi franc dans ses réponses mais un peu désabusé voire aigri…

Murray Wayper - CC by-nc-nd

Linus Torvalds se lâche sur Linux et Git

Linus Torvalds goes off on Linux and Git

Greg Jorgensen - 25 septembre 2012 - Typical Programmer
(Traduction : lgnap, Cyrille L., greygjhart, Gatitac, @adericbourg, lgodard, Penguin, Diwann, Florck + Anonymes)

J’étais dans un café à Portland dans l’Oregon quand j’ai remarqué Linus Torvalds assis seul à une table. J’ai demandé au créateur du noyau Linux et logiciel de gestion de versions Git si je pouvais me joindre à lui. Pendant 15 minutes, nous avons parlé de programmation et de programmeurs.

Typical Programmer Linux a été publié pour la première fois il y a maintenant 20 ans. C’est maintenant l’un des systèmes d’exploitation les plus répandus. Quel effet cela vous fait-il ?

Linus Torvalds Franchement, je suis très étonné. J’ai lancé ce projet comme un hobby et je n’en attendais pas grand chose. Au fur et à mesure que l’intérêt pour Linux croissait, j’ai observé qu’il était utilisé principalement par les développeurs purs et durs et les geeks pour se différencier de la foule. Il y a beaucoup de personnes dans l’industrie logicielle qui aiment montrer qu’ils utilisent le logiciel ou le langage de programmation le plus récent. C’est une question de statut, un peu comme les personnes qui parlent de groupes de musique indépendants ou de films étrangers. Que ce soit Linux, Haskell, MongoDB ou n’importe quoi d’autre, tout groupe comporte au moins une personne qui passe son temps à parler de fermetures ou à expliquer comment il est en train de migrer son blog vers Node.js pour qui’il puisse supporter une augmentation de la charge.

TP Linux est maintenant grand public. Est-ce devenu trop facile ?

Linus Je ne pense pas que ce soit plus facile, mais il y a beaucoup plus de ressources maintenant. Dans la plupart des cas, Linux est plus difficile à comprendre et à utiliser que Windows ou MacOS. Les personnes qui l’utilisent pour les serveurs avaient déjà l’habitude d’Unix, le changement n’était donc pas très important pour eux. Ils connaissaient les conflits de mises à jour et de dépendances et le cauchemar des bibliothèques partagées. Sur les postes de travail, je pense que les gens s’en sont désintéressés après quelques années.

TP Une perte d’intérêt ? de motivation ?

Linus Personne ne s’emballe plus pour les terminaux à fenêtre transparente , pour les palettes de couleur de Kate ou pour être le premier à expliquer sur Slashdot comment faire marcher telle mystérieuse carte son. Ça, c’était ce qui faisait passer les précurseurs de Windows à Linux. Maintenant Linux ressemble à Windows. Je peux installer Ubuntu sur le portable de ma grand-mère et elle ne voit même pas la différence tant que l’icône Facebook est sur son écran.

TP Et au sujet du nombre de distributions ? On dirait qu’il y a plus de distributions que d’utilisateurs finaux sous Linux.

Linus Il y a plus de distributions Linux sur un seul disque Linux Format que toutes les versions Windows réunies. Mais elles sont toutes à peu près similaires. Ce sont toutes à peu près la même chose réchauffée. Seuls des noms plus ou moins ingénieux ou drôles les distinguent les unes des autres. À partir du moment où un livre Linux pour les nuls a été publié, j’ai commencé à m’en désintéresser.

TP Vous avez publié le système de gestion de versions Git il y a moins de dix ans. Git est rapidement devenu à la mode et semble être majoritaire parmi les systèmes de gestion de versions, ou au moins celui que les gens recommandent le plus sur Reddit et HackerNews.

Linus Git a repris le relais parce que Linux commençait à ne plus trop séparer les gourous des ignorants. Je ne m’attendais pas vraiment à ce que quiconque l’utilise parce que c’est tellement dur à utiliser, mais finalement cela s’est révélé être son principal attrait. Aucune technologie ne saura jamais être trop compliquée ou trop obscure pour les barbus à t-shirt noirs.

TP Je trouvais déjà que Subversion était difficile d’accès. Je ne me suis pas encore cassé la tête avec Git.

Linus Vous allez passer beaucoup de temps à essayer de vous familiariser avec, tout en étant ridiculisé par les experts sur GitHub et ailleurs. J’ai appris qu’aucune toolchain n’est jamais trop compliquée car le besoin de prestige et la sécurité de l’emploi sont trop forts. Au bout du compte, vous allez vous aussi découvrir l’Easter egg dans Git : toutes les opérations significatives peuvent être exprimées à l’aide la commande rebase.

TP Que pensez-vous de GitHub du coup ?

Linus Ça a commencé comme un cocon, un sorte de cimetière pour projets non maintenus ou inutiles, et c’est toujours la majorité de ce qui y est hébergé. Mais c’est devenu aujourd’hui une sorte de grand World of Warcraft pour développeurs, où ils sont notés en fonction de leurs contributions et des projets sur lesquels ils ont les privilèges trunk. J’ai entendu dire que des boîtes informatiques recrutaient désormais à partir de votre réputation GitHub, alors j’imagine que si vous ne committez rien vous n’obtiendrez plus de boulot dans les start-ups les plus cools. Le bon vieux temps où l’on faisait passer le test du FizzBuzz et où on demandait comment faire pour déplacer le mont Fuji pendant les entretiens d’embauche est révolu.

TP Vous semblez un peu aigri au sujet de Git.

Linus Vous verrez, les premiers livres Git pour les nuls et Git Visual Quickstart vont paraître dans quelques mois et, en ce qui me concerne, ce sera le début de la fin. Ces livres marquent la fin d’une certaine expertise sur Git et de la réputation sur GitHub comme indicateurs fiables de la qualité du geek. Une fois qu’une technologie est adoptée par la masse, les geeks les plus geeks la délaissent au profit de quelque chose de plus ésotérique encore. Regardez ce qui est arrivé à Ruby on Rails. Les gens qui se forment à partir de tutoriels, de « todo lists » Rails, n’ont même jamais entendu parler de DHH.

TP Et pour la suite ?

Linus Je ne suis pas sûr. Difficile de prédire la prochaine mode technologique. J’ai travaillé sur un éditeur de texte que j’utilise moi-même, si compliqué qu’il ferait passer Vim pour Notepad, peut-être que je le publierai un de ces quatre.

Linus a terminé son café et a dû partir. J’ai apprécié le temps qu’il m’a consacré et de m’avoir fait voir Linux et Git sous un jour nouveau.

Crédit photo : Murray Wayper (Creative Commons By-Nc-Nd)

NdT : Oups, j’oubliais, Greg Jorgensen a publié son billet sous le tag « satire ». Je dis ça, je dis rien… Ça vous apprendra à ne pas lire jusqu’au bout :P

Gravatar de Framablog
Original post of Framablog.Votez pour ce billet sur Planet Libre.

Nicolargo : Installer facilement NodeJS et NPM sur une Debian Stable

mercredi 26 septembre 2012 à 12:15

A l'heure actuelle, il n'existe pas de dépôt officiel pour installer NodeJS et NPM sur une distribution Debian Stable. Voici donc un nouveau script d'installation automatique qui va installer sur votre système Debian:

Comme toujours, mon script est hébergé sur GitHub. C'est à partir de là que vous pouvez me remonter vos questions et remarques...

Procédure à suivre

Le plus simple est de saisir les commande suivantes dans un terminal:

cd /tmp
wget https://raw.github.com/nicolargo/nodeautoinstall/master/nodeautoinstall.py
sudo python ./nodeautoinstall.py -d

Le script va normalement se dérouler sans problème en installant le tout dans le répertoire /opt/node (qu'il est possible de modifier avec l'option -o du script).

L'option -d permet de générer un fichier de log de l’exécution du script (à consulter en cas de problème...) dans le fichier /tmp/nodeautoinstall.log.

Pour que votre/vos utilisateurs puisse utiliser node, il faut également qu'ils ajoutent les lignes suivantes au fichier .profile:

# --- NodeJS
export PATH=$PATH:/opt/node/bin
export NODE_PATH=/opt/node:/opt/node/lib/node_modules
# ---

Le résultat...

Vous devriez alors disposer des dernières versions des deux composants:

Il ne vous reste plus qu'à suivre mon billet d'introduction à NodeJS en passant le chapitre sur l'installation que vous venez de faire automatiquement dans ce billet:)

Cet article Installer facilement NodeJS et NPM sur une Debian Stable est apparu en premier sur Le blog de NicoLargo.

Gravatar de Nicolargo
Original post of Nicolargo.Votez pour ce billet sur Planet Libre.

Bastnic : Dette technique et open government

mercredi 26 septembre 2012 à 12:02

Depuis les dernières actualités, l'effectif de JoliCode a doublé et est encore en passe d'augmenter. Tout roule de ce côté là : super ambiance, bientôt des locaux super chouettes et des projets qui nous font oublier de s'ennuyer.

J'ai commis un article de vulgarisation sur la "dette technique" sur le Train de 13h37, j'espère que vous apprécierez et que vos projets s'en porteront mieux (et vous aussi donc).

Pour continuer dans la lignée des conférences PHP, où j'en ai animé deux en 2010 et 2012, et où j'étais présent au PHP Tour de Lilles, je serais encore présent à Nantes les 29 et 30 novembre 2012 pour animer une conférence sur "En complément de l'OpenData, l'opengovernment ou "Smartgov"", toujours en compagnie de Simon Perdrisat. Vous y retrouverez comme d'habitude plein de conférences intéressantes notamment sur les sujets de OpenData, les protocoles ouverts et les moyens de communication. Mais aussi une nouvelle conférence sur les tests avec Atoum par l'excellent Frédéric Hardy.

Gravatar de Bastnic
Original post of Bastnic.Votez pour ce billet sur Planet Libre.