1、FTP服務器
javascript
FTP,File Transfer Protocol 文件傳輸協議,FTP協議是一種古老的協議,它出現的比HTTP協議還要早,FTP主要應用於網絡空間數據交換操做。ftp在工做時會有兩個鏈接:一是命令鏈接,這個鏈接始終存在,只有使用bye命令退出會話時,鏈接纔會斷開;二是數據鏈接,數據傳輸完成,鏈接即斷開。ftp有兩種工做模式,主動模式和被動模式,主動模式工做在tcp/20端口,而被動模式則工做在tcp協議下的隨機端口。一般FTP在身份認證時工做在21號端口。php
在紅帽系統下,vsftp是一款相對安全的FTP軟件,在生產環境下可使用它快速的實現FTP服務器的搭建。vsftp的用戶認證支持兩類用戶,一是系統用戶,二是虛擬用戶。系統用戶故名思義,就是使用系統上的普通用戶做爲FTP用戶,這種方式操做相對簡單。而虛擬用戶則是使用一個系統用戶映射成全部虛擬用戶,訪問時的文件目錄是爲此係統用戶家目錄。虛擬用戶的用戶賬號信息的存儲分兩種方式,一是將用戶信息保存於一個hash編碼的文件,奇數行爲用戶名,偶數行爲密碼;二是,存儲於關係型數據庫。咱們知道,系統上幾乎全部的和賬號認證有關的操做都是經過系統的pam模塊負責管理,vsftp也不例外,咱們使用mysql管理vsftp的賬號密碼信息,則可使用pam的mysql模塊。pam默認不支持mysql數據庫,所以在使用前須要安裝此模塊。css
2、FTP服務器實現html
一、安裝軟件java
# yum -y install vsftpd mysql-server mysql-devel pam_mysql
二、建立數據庫mysql
mysql> create database vsftpd; mysql> grant all on vsftpd.* to 'vsftpuser'@'localhost' identified by 'vsftppass'; mysql> grant all on vsftpd.* to 'vsftpuser'@'127.0.0.1' identified by 'vsftppass'; mysql> grant all on vsftpd.* to 'vsftpuser'@'172.16.36.1' identified by 'vsftppass'; mysql> flush privileges; mysql> use vsftpd; mysql> create table users ( -> id int AUTO_INCREMENT NOT NULL, -> name char(20) binary NOT NULL, -> password char(48) binary NOT NULL, -> primary key(id) -> );
二、建立vsftp虛擬用戶linux
insert into users(name,password) values('wu',md5('wu')); insert into users(name,password) values('json',md5('json'));
三、創建pam認證所需文件web
#vi /etc/pam.d/vsftpd.mysql
添加以下兩行:sql
auth required /lib64/security/pam_mysql.so user=vsftpuser passwd=vsftppass host=172.16.36.1 db=vsftpd table=users usercolumn=name passwdcolumn=password crypt=3 account required /lib64/security/pam_mysql.so user=vsftpuser passwd=vsftppass host=172.16.36.1 db=vsftpd table=users usercolumn=name passwdcolumn=password crypt=3
user: 數據庫用戶名數據庫
passwd: 數據庫用戶密碼
host: 爲數據庫主機IP地址,若是是編譯安裝的數據庫,只能填寫遠程IP地址,並給把這個IP地址受權給用戶
db: 數據庫名
table: 表名
usercolumn: 用戶字段名
passwdcolumn: 用戶密碼字段名
crypt: 密碼保存方式,0爲明文,1爲encrypt函數加密,2爲password函數加密,3爲MD5加密
注意:因爲mysql的安裝方式不一樣,pam_mysql.so基於unix sock鏈接mysql服務器時可能會出問題,此時,建議受權一個可遠程鏈接的mysql並訪問vsftpd數據庫的用戶。
四、創建虛擬用戶映射的系統用戶及對應的目錄
# useradd -s /sbin/nologin -d /var/ftproot vuser # chmod go+rx /var/ftproot
五、請確保/etc/vsftpd/vsftpd.conf中已經啓用瞭如下選項
anonymous_enable=NO #禁止匿名用戶登陸 local_enable=YES #容許本地用戶登陸 write_enable=YES #本地用戶有寫權限 anon_upload_enable=NO #匿名用戶沒有上傳權限 anon_mkdir_write_enable=NO #匿名用戶沒有建立權限 chroot_local_user=YES #禁錮用戶家目錄
然後添加如下選項
guest_enable=YES guest_username=vuser
並確保pam_service_name選項的值以下所示
pam_service_name=vsftpd.mysql
六、從新啓動服務,測試一下。
service vsftpd restart
打開CMD程序遠程測試一下:
兩個賬號都能成功登陸!
2、經過web管理VSFTP
使用mysql管理vsftp用戶的一個好處是,當服務器數據遷移時,只要把相關的數據庫打包備份導入新的數據庫就好了,管理至關方便。若是本機上有web服務器的話,咱們還可使用PHP開發一個web界面專門用來管理vsftp。
例如:咱們新建一個虛擬主機:
<VirtualHost *:80> DocumentRoot "/var/www/html/vsftpadmin" ServerName ftpadmin.wubinary.com ServerAlias ftpadmin.wubinary.com ErrorLog "logs/ftpadmin.wubinary.com.error_log" CustomLog "logs/ftpadmin.wubinary.com.access_log" common ProxyRequests Off ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/var/www/html/vsftpadmin/$1 <Directory "/var/www/html/vsftpadmin"> Options None AllowOverride AuthConfig AuthType Basic AuthName "Vsftp Admin" AuthUserFile /etc/httpd/extra/.htpasswd Require valid-user </Directory> </VirtualHost>
對這個域名做身份認證,或者使用其它的方式對用戶進行限制,用PHP寫一個管理頁面放在相關的目錄下,咱們就能夠在web界面下管理咱們的FTP服務器賬號了。
整個FTP服務器的搭建工做到此就完成了。vsftp web管理界面的PHP源碼以下:
vsftpadmin.php
<?php header("Content-Type:text/html;charset=utf-8"); error_reporting(E_ALL & ~ E_NOTICE); //提示窗 function alertExit($msg,$flush=0){ // echo "<script language='javascript'>alert($msg);</script>"; echo "<script type='text/javascript' language='javascript'>alert('$msg');</script>"; if ($flush == 1) { echo "<script type='text/javascript' language='javascript'>window.location.href='vsftpadmin.php'</script>"; }elseif ($flush == 2) { echo "<script type='text/javascript' language='javascript'>history.back();self.location.reload();</script>"; } } //輸出頭部 function htmlheader($title){ echo <<<EOF <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>{$title}</title> <meta name="description" content="vsftp管理工具"> <meta name="keywords" content="linux,ftp,vsftp,mysql,pam_mysql,php"> <style type="text/css"> *{margin:0; padding:0; font-size:12px;} ul,li{ list-style:none;} a {text-decoration:none;color:#37a} a:hover { background:#37a;color:white;padding:2px;} img { border:0;} .clear{ clear:both;} .right{ float:right;} .left{ float:left;} #content{width:560px;margin:0 auto;text-align:center;margin-top:40px;} .admin{border:1px solid #ccc; padding:30px;text-align:left;} .admin h4{margin:10px 0;} .admin p{margin:10px 0;} .admin p .btn{padding:2px 4px;} </style> </head> <body> <div id="content"> <div class="admin"> <h4>{$title}</h4> <p class="admin_btn">管理菜單:<a href="?ac=ftp">ftp狀態</a> <a href="vsftpadmin.php">用戶列表</a> <a href="?ac=add">添加用戶</a></p> EOF; } //輸出尾部 function htmlfooter(){ echo <<<EOF </div> </div> </body> </html> EOF; } //查詢 function query($sql){ $result = mysql_query($sql) or die ("SQL語句查詢錯誤: " . mysql_error()); if (mysql_num_rows($result) == 0) { die('SQL: '.$sql.'<br>未查詢到相關數據'); } $arrReturn = array(); $index = 0; while($arr = mysql_fetch_assoc($result)){ $arrReturn[$index] = $arr; $index++; } return $arrReturn; } //添加 function adduser($name,$password){ if (strlen($name)<3) { alertExit('用戶名至少三位!',1); } if (strlen($password)<6) { alertExit('密碼必須大於八位!',1); } $sql = "select * from users where name='$name'"; $result = mysql_query($sql) or die ("SQL語句查詢錯誤: " . mysql_error()); if (mysql_num_rows($result) > 0) { alertExit('用戶已存在',1); }else{ $sql = "insert into users(name,password) values('$name',md5('$password'))"; $result = mysql_query($sql) or die ("添加角戶出錯: " . mysql_error()); // echo mysql_affected_rows(); if(mysql_affected_rows()==1){ alertExit("添加用戶成功!",2); } } } //刪除 function deluser($id){ $sql = 'select * from users where id='.$id; $result = mysql_query($sql) or die ("SQL語句查詢錯誤: " . mysql_error()); if (mysql_num_rows($result) == 0) { alertExit('用戶不存在',1); }else{ $sql = 'delete from users where id='.$id; $result = mysql_query($sql) or die ("刪除角戶出錯: " . mysql_error()); if(mysql_affected_rows()==1){ alertExit("刪除用戶成功!",1); } } } //修改 function moduser($id,$name,$password){ $sql = "select * from users where id=$id"; $result = mysql_query($sql) or die ("SQL語句查詢錯誤: " . mysql_error()); if (mysql_num_rows($result) == 0) { alertExit('用戶不存在',1); }else{ $sql = "select * from users where name='$name' and id!=$id"; $result = mysql_query($sql) or die ("SQL語句查詢錯誤: " . mysql_error()); if (mysql_num_rows($result) > 0) { alertExit('用戶已存在',1); }else{ $sql = "update users set name='$name', password='$password' where id=$id"; $result = mysql_query($sql) or die ("修改角戶出錯: " . mysql_error()); if(mysql_affected_rows()==1){ alertExit("修改用戶成功!",1); } alertExit("未做任何操做!",1); } } } //ftp狀態管理 function ftpadmin($service='status'){ $arrFtp = array(); $result = mysql_query("SELECT id FROM users"); $num_rows = mysql_num_rows($result); $arrFtp['usercount'] = $num_rows; if($service=='status'){ $arrFtp['status'] = `service vsftpd status`; }elseif($service=='restart'){ $arrFtp['status'] = `service vsftpd restart`; }elseif ($service=='stop') { $arrFtp['status'] = `service vsftpd stop`; } if(empty($arrFtp['status'])){ $arrFtp['status'] = 'Unknow'; } return $arrFtp; } $conn = @mysql_connect('127.0.0.1','root','') or die ('數據庫鏈接錯誤: ' . mysql_error()); mysql_select_db('vsftp', $conn) or die ('選擇數據庫錯誤: ' . mysql_error()); $strAction = htmlspecialchars($_GET['ac']); $arrAction = array('del', 'mod', 'add', 'ftp'); if (! in_array($strAction, $arrAction)) { htmlheader('Vsftp 管理'); $arrUserList = query('select * from users'); foreach ($arrUserList as $key => $value) { ?> <form action='./vsftpadmin.php?ac=mod' method='post'> <p><label>name:</label> <input type="text" name="name" value="<?php echo $value['name'];?>"> <label>password:</label> <input type="password" name="password" value="<?php echo $value["password"];?>"> <input type='hidden' name='id' value="<?php echo $value["id"];?>"> <input type="submit" value="修改" class="btn"> <input type="button" onclick="window.location.href='?id=<?php echo $value["id"];?>&ac=del'" value="刪除" class="btn"></p> </form> <?php } htmlfooter(); }else{ if ($strAction=='add') { if ($_SERVER['REQUEST_METHOD']=='POST') { $name = htmlspecialchars($_POST['name']); $password = htmlspecialchars($_POST['password']); adduser($name,$password); }else{ htmlheader('添加用戶'); ?> <form action='./vsftpadmin.php?ac=add' method='post'> <p><label>name:</label> <input type="text" name="name" value=""> <label>password:</label> <input type="password" name="password" value=""> <input type="submit" value="提交" class="btn"> <input type="reset" value="重置" class="btn"></p> </form> <?php htmlfooter(); } }elseif ($strAction=='del') { $intId = intval($_GET['id']); if($intId!=''){ deluser($intId); }else{ alertExit('參數錯誤!',1); } }elseif ($strAction=='mod') { $intId = intval($_POST['id']); $name = htmlspecialchars($_POST['name']); $password = htmlspecialchars($_POST['password']); if($name!='' && $password!=''){ moduser($intId,$name,$password); }else{ alertExit('參數錯誤!',1); } }elseif($strAction=='ftp'){ htmlheader('FTP狀態'); $arrFtp = array(); $status = htmlspecialchars($_GET['status']); if($status=='restart')$arrFtp = ftpadmin('restart'); elseif($status=='stop')$arrFtp = ftpadmin('stop'); else $arrFtp = ftpadmin(); ?> <p><label>用戶總數:</label> <?php echo $arrFtp['usercount'];?> <br> <label>vsftp狀態:</label> <?php echo $arrFtp['status'];?> <input type="button" onclick="window.location.href='?ac=ftp&status=restart'" value="重啓" class="btn"> <input type="button" onclick="window.location.href='?ac&status=stop'" value="中止" class="btn"></p> <?php htmlfooter(); }else{ die('無效的地址!'); } }