py-FTP服務(wù)器之四:ftp主程序

關(guān)于pyftpdlib建立 FTP服務(wù)器的詳細(xì)內(nèi)容:
py-FTP服務(wù)器之一:虛擬運(yùn)行環(huán)境
py-FTP服務(wù)器之二:用戶(hù)配置文件
py-FTP服務(wù)器之三:?jiǎn)⒂肧SL連接
py-FTP服務(wù)器之四:ftp主程序
py-FTP服務(wù)器之五:其他

  • 主程序是ftp.py
  • ftp.py同級(jí)要有一個(gè)rootftp文件夾, 作為根目錄, ftp上傳來(lái)的文件全部丟里面

關(guān)于是否啟用SSL加密和多進(jìn)程的代碼

# 是否啟用ssl加密和多進(jìn)程模式
USE_SSL = False  # 是否啟用ftps加密傳輸,通過(guò)修改單獨(dú)的文件設(shè)置,默認(rèn)是不用ssl
if 'ssl' in argv:
    USE_SSL = True  # 如果要啟用ssl,運(yùn)行時(shí)要加參數(shù) ssl
if 'mul' in argv:
    USE_MULTIPLE_PROCESS = True  # 開(kāi)啟多進(jìn)程模式, 運(yùn)行時(shí)要增加參數(shù) mul

注意: 在啟動(dòng)程序時(shí)需要在后面加參數(shù), 比如要啟用ssl, 則應(yīng)當(dāng)輸入python ftp.py ssl, 如果還要開(kāi)啟多進(jìn)程, 則應(yīng)輸入python ftp.py ssl mul

MD5驗(yàn)證函數(shù)

這個(gè)函數(shù)是在官方給的基礎(chǔ)上做了一些簡(jiǎn)化.

# 驗(yàn)證用戶(hù)密碼hash后是否與原來(lái)的一樣,照著官方文檔寫(xiě)的,修改了一點(diǎn)
class DummyMD5Authorizer(DummyAuthorizer):
    def validate_authentication(self, username, password, handler):
        hash = md5(password.encode('utf-8')).hexdigest()  # 與md5USerPassword.py上的算法一致
        try:
            if self.user_table[username]['pwd'] != hash:
                raise KeyError
        except KeyError:
            raise AuthenticationFailed

從文本文件加載用戶(hù)信息

# 讀取用戶(hù)權(quán)限文件,向虛擬用戶(hù)管理器添加用戶(hù)
def add_user(authorizer):

    # 用戶(hù)權(quán)限文件
    userfile = 'userMD5.txt'  # 文件格式如下(md5加密后的文件,運(yùn)行md5UserPassword.py后自動(dòng)生成)
    '''
        # 備注文字(用tab間隔開(kāi)來(lái))
        username    md5(password)    path    perm
        username    md5(password)    path    perm
        username    md5(password)    path    perm
    '''

    # 用戶(hù)列表
    user_list = []
    split_str = '\t'

    # 從userMD5.txt讀取用戶(hù)信息
    with open(userfile) as f:
        for line in f:
            line = line.replace('\n', '')  # 去掉最后的\n
            if not line.startswith('#') and line:  # #后面是備注
                if len(line.split(split_str)) == 4:  # 用戶(hù)名/密碼/路徑/權(quán)限
                    user_list.append(line.split(split_str))
                else:
                    print("userMD5.txt配置錯(cuò)誤: %s" % line)

    # 添加用戶(hù)
    for user in user_list:
        authorizer.add_user(user[0], user[1], './rootftp' + user[2], perm=user[3], msg_login="歡迎光臨", msg_quit="歡迎下次光臨")
        print('[%s\t---\t%s\t%s]' % (user[0], user[3], user[2]))

    # 返回虛擬用戶(hù)管理器
    return authorizer

被動(dòng)模式PASV

  • 如果有電腦在局域網(wǎng)中要連接外網(wǎng)的FTP, 則建議使用被動(dòng)模式PASV進(jìn)行連接
  • 設(shè)置一個(gè)假的IP地址, 確定一個(gè)被動(dòng)模式端口的范圍(默認(rèn)設(shè)置為這個(gè), 服務(wù)器的最后5000多個(gè)端口號(hào))
# 被動(dòng)模式配置
    # Specify a masquerade address and the range of ports to use for
    # passive connections.  Decomment in case you're behind a NAT.
    # 設(shè)置假I(mǎi)P地址發(fā)回給ftp客戶(hù)端,設(shè)置被動(dòng)模式的端口區(qū)間(最大65535)
    handler.masquerade_address = '151.25.42.11'  # ftp服務(wù)器的偽IP地址
    handler.passive_ports = range(60000, 65535)  # 被動(dòng)模式下的隨機(jī)端口

完整代碼ftp.py

# coding:utf-8
from pyftpdlib.servers import FTPServer, MultiprocessFTPServer
from pyftpdlib.authorizers import DummyAuthorizer, AuthenticationFailed
from hashlib import md5
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.handlers import TLS_FTPHandler  # TLS_FTPHandler需要pip安裝pyopenssl
from sys import argv  # 用來(lái)讀取啟動(dòng)py文件時(shí)的命令行參數(shù)


# 是否啟用ssl加密
USE_SSL = False  # 是否啟用ftps加密傳輸,通過(guò)修改單獨(dú)的文件設(shè)置,默認(rèn)是不用ssl
if 'ssl' in argv:
    USE_SSL = True  # 如果要啟用ssl,運(yùn)行時(shí)要加參數(shù) ssl
if 'mul' in argv:
    USE_MULTIPLE_PROCESS = True  # 開(kāi)啟多進(jìn)程模式


# 驗(yàn)證用戶(hù)密碼hash后是否與原來(lái)的一樣,照著官方文檔寫(xiě)的,修改了一點(diǎn)
class DummyMD5Authorizer(DummyAuthorizer):
    def validate_authentication(self, username, password, handler):
        hash = md5(password.encode('utf-8')).hexdigest()  # 與md5USerPassword.py上的算法一致
        try:
            if self.user_table[username]['pwd'] != hash:
                raise KeyError
        except KeyError:
            raise AuthenticationFailed


# 讀取用戶(hù)權(quán)限文件,向虛擬用戶(hù)管理器添加用戶(hù)
def add_user(authorizer):

    # 用戶(hù)權(quán)限文件
    userfile = 'userMD5.txt'  # 文件格式如下(md5加密后的文件,運(yùn)行md5UserPassword.py后自動(dòng)生成)
    '''
        # 備注文字(用tab間隔開(kāi)來(lái))
        username    md5(password)    path    perm
        username    md5(password)    path    perm
        username    md5(password)    path    perm
    '''

    # 用戶(hù)列表
    user_list = []
    split_str = '\t'

    # 從userMD5.txt讀取用戶(hù)信息
    with open(userfile) as f:
        for line in f:
            line = line.replace('\n', '')  # 去掉最后的\n
            if not line.startswith('#') and line:  # #后面是備注
                if len(line.split(split_str)) == 4:  # 用戶(hù)名/密碼/路徑/權(quán)限
                    user_list.append(line.split(split_str))
                else:
                    print("userMD5.txt配置錯(cuò)誤: %s" % line)

    # 添加用戶(hù)
    for user in user_list:
        authorizer.add_user(user[0], user[1], './rootftp' + user[2], perm=user[3], msg_login="歡迎光臨", msg_quit="歡迎下次光臨")
        print('[%s\t---\t%s\t%s]' % (user[0], user[3], user[2]))

    # 返回虛擬用戶(hù)管理器
    return authorizer


#
def main():
    # 用戶(hù)驗(yàn)證
    # Instantiate a dummy authorizer for managing 'virtual' users 創(chuàng)建虛擬用戶(hù)管理器
    # authorizer = DummyAuthorizer()
    authorizer = DummyMD5Authorizer()  # 因?yàn)橐?yàn)證hash值,所以改成這個(gè)了類(lèi)了,官方寫(xiě)的, 這個(gè)類(lèi)繼承自DummyAuthorizer類(lèi)

    # Define a new user having full r/w permissions and a read-only anonymous user
    # 讀取userMD5.txt文件,綁定 用戶(hù)-權(quán)限
    authorizer = add_user(authorizer)  # 寫(xiě)成了一個(gè)函數(shù)add_user()來(lái)自動(dòng)讀取userMD5.txt
    # authorizer.add_anonymous(os.getcwd())  # 匿名用戶(hù),關(guān)閉

    # ftp主控制器
    # Instantiate FTP handler class
    # 綁定FTP控制器
    if not USE_SSL:
        handler = FTPHandler  # ftp傳輸
    if USE_SSL:
        handler = TLS_FTPHandler  # ftps傳輸 = ftp + ssl
    handler.authorizer = authorizer  # 綁定用戶(hù)管理器

    # ssl加密
    if USE_SSL:
        handler.certfile = 'crt_key.pem'  # 此處需要插入自簽名證書(shū)文件base64編碼的pem
        # requires SSL for both control and data channel
        # 啟用ssl加密傳輸
        # handler.tls_control_required = True  # 控制連接啟用ssl加密
        handler.tls_data_required = True  # 數(shù)據(jù)連接啟用ssl加密

    # 錦上添花
    # Define a customized banner (string returned when client connects)
    # 定義ftp客戶(hù)端[連接成功歡迎詞]
    handler.banner = "歡迎你我尊貴的客人蒞臨指導(dǎo)"

    # 被動(dòng)模式配置
    # Specify a masquerade address and the range of ports to use for
    # passive connections.  Decomment in case you're behind a NAT.
    # 設(shè)置假I(mǎi)P地址發(fā)回給ftp客戶(hù)端,設(shè)置被動(dòng)模式的端口區(qū)間(最大65535)
    handler.masquerade_address = '151.25.42.11'  # ftp服務(wù)器的偽IP地址
    handler.passive_ports = range(60000, 65535)  # 被動(dòng)模式下的隨機(jī)端口

    # ip限制及端口設(shè)定
    # Instantiate FTP server class and listen on 0.0.0.0:8081
    # 設(shè)置不限制IP地址訪問(wèn),端口8081,使用TCP端口8081
    address = ('0.0.0.0', 8081)  # ip限制及連接端口(需要在安全組里放通這個(gè)端口)
    # 多進(jìn)程模式是否開(kāi)啟
    if USE_MULTIPLE_PROCESS:
        server = MultiprocessFTPServer(address, handler)
    else:
        server = FTPServer(address, handler)

    # 最大連接數(shù)限制
    # set a limit for connections
    # 設(shè)置最大連接數(shù),和相同IP地址的最大同時(shí)連接數(shù)
    server.max_cons = 50
    server.max_cons_per_ip = 20

    # 萬(wàn)事俱備,只欠東風(fēng)
    # start ftp server
    # 啟動(dòng)ftp服務(wù)器
    server.serve_forever()


# 啟動(dòng)
if __name__ == '__main__':
    main()

啟動(dòng)

啟動(dòng)命令: python ftp.py ssl mul
后臺(tái)運(yùn)行: nohup python ftp.py >> log 2>&1 &

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末刀脏,一起剝皮案震驚了整個(gè)濱河市弦疮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌规揪,老刑警劉巖宴合,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件市栗,死亡現(xiàn)場(chǎng)離奇詭異姿鸿,居然都是意外死亡榨了,警方通過(guò)查閱死者的電腦和手機(jī)袍暴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)些侍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人政模,你說(shuō)我怎么就攤上這事岗宣。” “怎么了淋样?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵耗式,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我趁猴,道長(zhǎng)刊咳,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任儡司,我火速辦了婚禮娱挨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘捕犬。我一直安慰自己跷坝,他們只是感情好酵镜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著柴钻,像睡著了一般淮韭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贴届,一...
    開(kāi)封第一講書(shū)人閱讀 51,274評(píng)論 1 300
  • 那天靠粪,我揣著相機(jī)與錄音,去河邊找鬼粱腻。 笑死庇配,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绍些。 我是一名探鬼主播捞慌,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼柬批!你這毒婦竟也來(lái)了啸澡?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤氮帐,失蹤者是張志新(化名)和其女友劉穎嗅虏,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體上沐,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡皮服,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了参咙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片龄广。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蕴侧,靈堂內(nèi)的尸體忽然破棺而出择同,到底是詐尸還是另有隱情,我是刑警寧澤净宵,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布敲才,位于F島的核電站,受9級(jí)特大地震影響择葡,放射性物質(zhì)發(fā)生泄漏紧武。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一敏储、第九天 我趴在偏房一處隱蔽的房頂上張望脏里。 院中可真熱鬧,春花似錦虹曙、人聲如沸迫横。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)矾踱。三九已至恨狈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間呛讲,已是汗流浹背禾怠。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留贝搁,地道東北人吗氏。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像雷逆,于是被迫代替她去往敵國(guó)和親弦讽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354