2015年7月

通过运行在 Android 手机上的自制遥控器来控制你的家庭媒体播放器。

Kodi 是一款很优秀的软件,能够将几乎所有电脑变身成媒体中心。它可以播放音乐和视频,显示图片,甚至还能显示天气预报。为了在配置成家庭影院后方便使用,你可以通过手机 app 访问运行在连接到 Wi-Fi 的 XBMC 机器上的服务来控制它。可以找到很多这种工具,几乎覆盖所有智能手机系统。

XBMC

Kodi 原名叫做 XBMC,在你阅读这篇文章的时候,XBMC 已经成为历史。因为法律原因(因为名字 XBMC 或 X-Box Media Center 里引用了不再支持的过时硬件)项目组决定使用新的名字 Kodi。不过,除了名字,其他的都会保持原样。或者说除开通常新版本中所期待的大量新改进。这一般不会影响到遥控软件,它应该能在已有的 XBMC 系统和新的 Kodi 系统上都能工作。

我们目前已经配置好了一个用于播放音乐的 Kodi 系统,不过我们找到的所有 Kodi 遥控没一个好用的,特别是和媒体中心连接的电视没打开的时候。它们都有点太复杂了,集成了太多功能在手机的小屏幕上。我们希望能有这样的系统,从最开始就是设计成只用于访问音乐库和电台插件,所以我们决定自己实现一个。它不需要用到 Kodi 的所有功能,因为除了音乐以外的任务,我们可以简单地切换使用通用的 Kodi 遥控。我们的测试系统是一个刷了 RaspBMC 发行版的树莓派,但是我们要做的工具并不受限于树莓派或Kodi那个发行版,它应该可以匹配任何安装了相关插件的基于 Linux 的 Kodi 系统。

首先,遥控程序需要一个用户界面。大多数 Kodi 遥控程序都是独立的 app。不过对于我们要做的这个音乐控制程序,我们希望用户可以不用安装任何东西就可以使用。显然我们需要使用网页界面。Kodi 本身自带网页服务器,但是为了获得更多权限,我们还是使用了独立的网页框架。在同一台电脑上跑两个以上网页服务器没有问题,只不过它们不能使用相同的端口。

有几个网页框架可以使用。而我们选用 Bottle 是因为它是一个简单高效的框架,而且我们也确实用不到任何高级功能。Bottle 是一个 Python 模块,所以这也将是我们编写服务器模块的语言。

你应该能在软件包管理器里找到 Bottle。在基于 Debian 的系统(包括 RaspBMC)里,你可以通过下面的命令安装:

sudo apt-get install python-bottle

遥控程序实际上只是连接用户和系统的中间层。Bottle 提供了和用户交互的方式,而我们将通过 JSON API 来和 Kodi 交互。这样可以让我们通过发送 JSON 格式消息的方式去控制媒体播放器。

我们将用到一个叫做 xbmcjson 的简单 XBMC JASON API 封装。足够用来发送控制请求,而不需要关心实际的 JSON 格式以及和服务器通讯的无聊事。它没有包含在 PIP 包管理中,所以你得直接从 GitHub 安装:

git clone https://github.com/jcsaaddupuy/python-xbmc.git
cd python-xbmc
sudo python setup.py install

万事俱备,只欠代码。

先从 Bottle 开始

我们程序的基本结构:

from xbmcjson import XBMC
from bottle import route, run, template, redirect, static_file, request
import os
xbmc = XBMC("http://192.168.0.5/jsonrpc", "xbmc", "xbmc")
@route('/hello/<name>')
def index(name):
return template('<h1>Hello {{name}}!</h1>', name=name)
run(host="0.0.0.0", port=8000)

这样程序将连接到 Kodi(不过实际上用不到);然后 Bottle 会开始提供网站服务。在我们的代码里,它将监听主机 0.0.0.0(意味着允许所有主机连接)的端口 8000。它只设定了一个站点,就是 /hello/XXXX,这里的 XXXX 可以是任何内容。不管 XXXX 是什么都将作为参数名传递给 index()。然后再替换进去 HTML 网页模版。

你可以先试着把上面内容写到一个文件(我们取的名字是 remote.py),然后用下面的命令启动:

python remote.py

然后你可以在浏览器里访问 localhost:8000/hello/world 看看模版生效的效果。

@route() 用来设定网页服务器的路径,而函数 index() 会返回该路径的数据。通常是返回由模版生成的 HTML 页面,但是并不是说只能这样(后面会看到)。

随后,我们将给应用添加更多页面入口,让它变成一个全功能的 Kodi 遥控,但仍将采用相同代码结构。

XBMC JSON API 接口可以从和 Kodi 机器同网段的任意电脑上访问。也就是说你可以在自己的笔记本上开发,然后再布置到媒体中心上,而不需要浪费时间上传每次改动。

模版 - 比如前面例子里的那个简单模版 - 是一种结合 Python 和 HTML 来控制输出的方式。理论上,这俩能做很多很多事,但是会非常混乱。我们将只是用它们来生成正确格式的数据。不过,在开始动手之前,我们先得准备点数据。

Paste

Bottle 自带网页服务器,我们用它来测试遥控程序。不过,我们发现它性能有时不够好。当我们的遥控程序正式上线时,我们希望页面能更快一点显示出来。Bottle 可以和很多不同的网页服务器配合工作,而我们发现 Paste 用起来非常不错。而要使用的话,只要简单地安装(Debian 系统里的 python-paste 包),然后修改一下代码里的 run 调用:

run(host=hostname, port=hostport, server="paste")

你可以在 http://bottlepy.org/docs/dev/deployment.html 找到如何使用其他服务器的相关细节。

从 Kodi 获取数据

XBMC JSON API 分成 14 个命名空间:JSONRPC, Player, Playlist, Files, AudioLibrary, VideoLibrary, Input, Application, System, Favourites, Profiles, Settings, Textures 和 XBMC。每个都可以通过 Python 的 XBMC 对象访问(Favourites 除外,明显是个疏忽)。每个命名空间都包含许多方法用于对程序的控制。例如,Playlist.GetItems() 可以用来获取某个特定播放列表的内容。服务器会返回给我们 JSON 格式的数据,但 xbmcjson 模块会为我们转化成 Python 词典。

我们需要用到 Kodi 里的两个组件来控制播放:播放器和播放列表。播放器处理播放列表并在每首歌结束时从列表里取下一首。为了查看当前正在播放的内容,我们需要获取正在工作的播放器的 ID,然后根据它找到当前播放列表的 ID。这个可以通过下面的代码来实现:

def get_playlistid():
player = xbmc.Player.GetActivePlayers()
if len(player['result']) > 0:
playlist_data = xbmc.Player.GetProperties({"playerid":0, "properties":["playlistid"]})
if len(playlist_data['result']) > 0 and "playlistid" in playlist_data['result'].keys():
return playlist_data['result']['playlistid']
return -1

如果当前没有播放器在工作(就是说,返回数据的结果部分的长度是 0),或者当前播放器没有处理播放列表,这样的话函数会返回 -1。其他时候,它会返回当前播放列表的数字 ID。

当我们拿到当前播放列表的 ID 后,就可以获取该列表的细节内容。按照我们的需求,有两个重要的地方:播放列表里包含的项,以及当前播放所处的位置(已经播放过的项并不会从播放列表移除,只是移动当前播放位置)。

def get_playlist():
playlistid = get_playlistid()
if playlistid >= 0:
data = xbmc.Playlist.GetItems({"playlistid":playlistid, "properties": ["title", "album", "artist", "file"]})
position_data = xbmc.Player.GetProperties({"playerid":0, 'properties':["position"]})
position = int(position_data['result']['position'])
return data['result']['items'][position:], position
return [], -1

这样可以返回正在播放的项开始的列表(因为我们并不关心已经播放过的内容),而且也包含了用来从列表里移除项的位置信息。

Image

API 文档在这里:http://wiki.xbmc.org/?title=JSON-RPC_API/v6。它列出了所有支持的函数,但是关于具体如何使用的描述有点太简单了。

JSON

JSON 是 JavaScript Object Notation 的缩写,最初设计用于 JavaScript 对象的序列化。目前仍然起到这个作用,但是它也是用来编码任意数据的一种很好用的方式。

JSON 对象都是这样的格式:

{property1:value1, property2:value2, property3:value3}

支持任意数目的属性/值配对。对 Python 程序员来说,看上去和字典数据结构很相似,不过这两个确实很像。

在字典数据结构里,值本身可以是另一个 JSON 对象,或者一个列表,所以下面的格式也是正确的:

{"name":"Ben", "jobs":["cook", "bottle-washer"], "appearance": {"height":195, "skin":"fair"}}

JSON 通常在网络服务中用来发送和接收数据,并且大多数编程语言都能很好地支持,所以如果你熟悉 Python 的话,你应该可以使用你熟悉的编程语言调用相同的接口来轻松地控制 Kodi。

整合到一起

把之前的功能连接到 HTML 页面很简单:

@route('/juke')
def index():
current_playlist, position = get_playlist()
return template('list', playlist=current_playlist, offset = position)

只需要抓取播放列表(调用我们之前定义的函数),然后将结果传递给负责显示的模版。

负责显示列表数据的模版的主要部分是:

<h2>Currently Playing:</h2>
% if playlist is not None:
% position = offset
% for song in playlist:
<strong> {{song['title']}} </strong>
% if song['type'] == 'unknown':
Radio
% else:
{{song['artist'][0]}}
% end
% if position != offset:
<a href="/remove/{{position}}">remove</a>
% else:
<a href="/skip/{{position}}">skip</a>
% end
<br>
% position += 1
% end

可以看到,模版大部分是用 HTML 写的,只有一小部分用来控制输出的其他代码。用两个大括号括起来的变量是输出位置(像我们在第一个 'hello world' 例子里看到的)。你也可以嵌入以百分号开头的 Python 代码。因为没有缩进,你需要用一个 % end 来结束当前的代码块(就像循环或 if 语句)。

这个模版首先检查列表是否为空,然后遍历里面的每一项。每一项会用粗体显示歌曲名字,然后是艺术家名字,然后是一个是否跳过(如果是当前正在播的歌曲)或从列表移除的链接。所有歌曲的类型都是 'song',如果类型是 'unknown',那就不是歌曲而是网络电台。

/remove/ 和 /skip/ 路径只是简单地封装了 XBMC 控制功能,在改动生效后重新加载 /juke:

@route('/skip/<position>')
def index(position):
print xbmc.Player.GoTo({'playerid':0, 'to':'next'})
redirect("/juke")
@route('/remove/<position>')
def index(position):
playlistid = get_playlistid()
if playlistid >= 0:
xbmc.Playlist.Remove({'playlistid':int(playlistid), 'position':int(position)})
redirect("/juke")

当然,如果不能往列表里添加歌曲的话那这个列表管理功能也不行。

因为一旦播放列表结束,它就消失了,所以你需要重新创建一个,这会让事情复杂一些。而且有点让人迷惑的是,播放列表是通过调用 Playlist.Clear() 方法来创建的。这个方法也还用来删除包含网络电台(类型是 unknown)的播放列表。另一个麻烦的地方是列表里的网络电台开始播放后就不会停,所以如果当前在播网络电台,也会需要清除播放列表。

这些页面包含了指向 /play/ 的链接来播放歌曲。通过下面的代码处理:

@route('/play/<id>')
def index(id):
playlistid = get_playlistid()
playlist, not_needed= get_playlist()
if playlistid < 0 or playlist[0]['type'] == 'unknown':
xbmc.Playlist.Clear({"playlistid":0})
xbmc.Playlist.Add({"playlistid":0, "item":{"songid":int(id)}})
xbmc.Player.open({"item":{"playlistid":0}})
playlistid = 0
else:
xbmc.Playlist.Add({"playlistid":playlistid, "item":{"songid":int(id)}})
remove_duplicates(playlistid)
redirect("/juke")

最后一件事情是实现 remove\_duplicates 调用。这并不是必须的 - 而且还有人并不喜欢这个 - 不过可以保证同一首歌不会多次出现在播放列表里。

我们也实现了一些页面用来列出收藏歌曲里所有艺术家,以及列出指定艺术家的歌曲和专辑。这些都非常简单,和 /juke 页面基本类似。

Image

还需要处理一下 UI,不过功能已经有了。

日志

通常拿到 XBMC JSON API 并不清楚能用来做什么,而且它的文档也有点模糊。找出如何使用的一种方式是看别的遥控程序是怎么做的。如果打开日志功能,就可以在使用其他遥控程序的时候看到哪个 API 被调用了,然后就可以应用到在自己的代码里。

要打开日志功能,把 Kodi 媒体中心 接到显示器上,再依次进入设置 > 系统 > 调试,打开允许调试日志。在打开日志功能后,还需要登录到 Kodi 机器上(比如通过 SSH),然后就可以查看日志了。日志文件的位置应该显示在 Kodi 界面左上角。在 RaspBMC 系统里,文件位置是 /home/pi/.xbmc/temp/xbmc.log。你可以通过下面的命令实时监视哪个 API 接口被调用了:

cd /home/pi/.xbmc/temp
tail -f xbmc.log | grep "JSON"

增加功能

上面的代码都是用来播放 Kodi 媒体库里的歌曲的,但我们还希望能播放网络电台。每个插件都有自己的独立 URL 可以通过普通的 XBMC JSON 命令来获取信息。举个例子,要从电台插件里获取选中的电台,可以使用;

@route('/radio/')
def index():
my_stations = xbmc.Files.GetDirectory({"directory":"plugin://plugin.audio.radio_de/stations/my/", "properties":
["title","thumbnail","playcount","artist","album","episode","season","showtitle"]})
if 'result' in my_stations.keys():
return template('radio', stations=my_stations['result']['files'])
else:
return template('error', error='radio')

这样可以返回一个可以和歌曲一样能添加到播放列表的文件。不过,这些文件能一直播下去,所以(之前说过)在添加其他歌曲的时候需要重新创建列表。

共享歌曲

除了伺服页面模版,Bottle 还支持静态文件,方便用于那些不会因为用户输入而改变的内容。可以是 CSS 文件,一张图片或是一首 MP3 歌曲。在我们的简单遥控程序里(目前)还没有任何用来美化的 CSS 或图片,不过我们增加了一个下载歌曲的途径。这个可以让媒体中心变成一个存放歌曲的 NAS 盒子。在需要传输大量数据的时候,最好还是用类似 Samba 的功能,但只是下几首歌到手机上的话使用静态文件也是很好的方式。

通过歌曲 ID 来下载的 Bottle 代码:

@route('/download/<id>')
def index(id):
data = xbmc.AudioLibrary.GetSongDetails({"songid":int(id), "properties":["file"]})
full_filename = data['result']['songdetails']['file']
path, filename = os.path.split(full_filename)
return static_file(filename, root=path, download=True)

应用的时候,只需要为 /songsby/ 页面里的相应 ID 加个链接。

我们已经把所有的代码过了一遍,不过还需要一点工作来把它们集合到一起。可以自己去 GitHub 页面 https://github.com/ben-ev/xbmc-remote 看下。

设置
我们的遥控程序已经开发完成,还需要保证让它在媒体中心每次开机的时候都能启动。有几种方式,最简单的是在 /etc/rc.local 里增加一行命令来启动。我们的文件位置在 /opt/xbmc-remote/remote.py,其他文件也和它一起。然后在 /etc/rc.local 最后的 exit 0 之前增加了下面一行。

cd /opt/xbmc-remote && python remote.py &

GitHub
这个项目目前还只是个架子,但是 - 我们运营杂志就意味着没有太多自由时间来编程。不过,我们启动了一个 GitHub 项目,希望能持续完善, 而如果你觉得这个项目有用的话,欢迎做出贡献。

要查看最新的进展,请访问 https://github.com/ben-ev/xbmc-remote 看看所处的状态。你可以从页面里获取最新的代码,或者通过命令行复制。

如果你希望改善它,可以复制项目到你自己的分支开发,然后在功能完成后发起合并请求。关于如何使用 GitHub 的更多信息,请访问 https://github.com/features


via: http://www.linuxvoice.com/xbmc-build-a-remote-control/

作者:Ben Everard 译者:zpl1025 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

虽然 Red Hat 已经发布了 RHEL 7.1,但是对 RHEL 6 系列的更新继续进行。最近,RedHat 发布了 RHEL 6 的最新更新版本 RHEL 6.7。

发布公告列出了主要的改进:

  • clufter:一个分析和转换集群配置格式的工具,clufter 可以让系统管理员更新现有的 HA 配置来运行 RedHat 最新的HA 工具。
  • LVM Cache 已经全部支持了,它允许用户在有限的成本下,最大化基于 SSD 的存储的性能。

发行备注中包括了更多细节和已知问题的列表。此外还提供一系列的更多细节的技术备注,包括软件包的改变和安全建议。

简介

要提供互联网服务,当你在开发代码的时候必须时刻保持安全意识。可能大部分 PHP 脚本都对安全问题都不在意,这很大程度上是因为有大量的无经验程序员在使用这门语言。但是,没有理由让你因为对你的代码的不确定性而导致不一致的安全策略。当你在服务器上放任何涉及到钱的东西时,就有可能会有人尝试破解它。创建一个论坛程序或者任何形式的购物车,被攻击的可能性就上升到了无穷大。

背景

为了确保你的 web 内容安全,这里有一些常规的安全准则:

别相信表单

攻击表单很简单。通过使用一个简单的 JavaScript 技巧,你可以限制你的表单只允许在评分域中填写 1 到 5 的数字。如果有人关闭了他们浏览器的 JavaScript 功能或者提交自定义的表单数据,你客户端的验证就失败了。

用户主要通过表单参数和你的脚本交互,因此他们是最大的安全风险。你应该学到什么呢?在 PHP 脚本中,总是要验证 传递给任何 PHP 脚本的数据。在本文中,我们向你演示了如何分析和防范跨站脚本(XSS)攻击,它可能会劫持用户凭据(甚至更严重)。你也会看到如何防止会玷污或毁坏你数据的 MySQL 注入攻击。

别相信用户

假定你网站获取的每一份数据都充满了有害的代码。清理每一部分,即便你相信没有人会尝试攻击你的站点。

关闭全局变量

你可能会有的最大安全漏洞是启用了 register\_globals 配置参数。幸运的是,PHP 4.2 及以后版本默认关闭了这个配置。如果打开了 register\_globals,你可以在你的 php.ini 文件中通过改变 register\_globals 变量为 Off 关闭该功能:

register_globals = Off 

新手程序员觉得注册全局变量很方便,但他们不会意识到这个设置有多么危险。一个启用了全局变量的服务器会自动为全局变量赋任何形式的参数。为了了解它如何工作以及为什么有危险,让我们来看一个例子。

假设你有一个称为 process.php 的脚本,它会向你的数据库插入表单数据。初始的表单像下面这样:

<input name="username" type="text" size="15" maxlength="64">

运行 process.php 的时候,启用了注册全局变量的 PHP 会将该参数赋值到 $username 变量。这会比通过 **$\_POST['username']$\_GET['username']** 访问它节省击键次数。不幸的是,这也会给你留下安全问题,因为 PHP 会设置该变量的值为通过 GET 或 POST 的参数发送到脚本的任何值,如果你没有显示地初始化该变量并且你不希望任何人去操作它,这就会有一个大问题。

看下面的脚本,假如 $authorized 变量的值为 true,它会给用户显示通过验证的数据。正常情况下,只有当用户正确通过了这个假想的 authenticated\_user() 函数验证,$authorized 变量的值才会被设置为真。但是如果你启用了 register\_globals,任何人都可以发送一个 GET 参数,例如 authorized=1 去覆盖它:

<?php
// Define $authorized = true only if user is authenticated
if (authenticated_user()) {
    $authorized = true;
}
?>

这个故事的寓意是,你应该从预定义的服务器变量中获取表单数据。所有通过 post 表单传递到你 web 页面的数据都会自动保存到一个称为 $\_POST** 的大数组中,所有的 GET 数据都保存在 **$\_GET 大数组中。文件上传信息保存在一个称为 $\_FILES** 的特殊数据中。另外,还有一个称为 **$\_REQUEST 的复合变量。

要从一个 POST 方法表单中访问 username 字段,可以使用 $\_POST['username']**。如果 username 在 URL 中就使用 **$\_GET['username']。如果你不确定值来自哪里,用 $\_REQUEST['username']

<?php
$post_value = $_POST['post_value'];
$get_value = $_GET['get_value'];
$some_variable = $_REQUEST['some_value']; 
?>  

$\_REQUEST 是 $\_GET、$\_POST、和 $\_COOKIE 数组的结合。如果你有两个或多个值有相同的参数名称,注意 PHP 会使用哪个。默认的顺序是 cookie、POST、然后是 GET。

推荐安全配置选项

这里有几个会影响安全功能的 PHP 配置设置。下面是一些显然应该用于生产服务器的:

  • register\_globals 设置为 off
  • safe\_mode 设置为 off
  • error\_reporting 设置为 off。如果出现错误了,这会向用户浏览器发送可见的错误报告信息。对于生产服务器,使用错误日志代替。开发服务器如果在防火墙后面就可以启用错误日志。(LCTT 译注:此处据原文逻辑和常识,应该是“开发服务器如果在防火墙后面就可以启用错误报告,即 on。”)
  • 停用这些函数:system()、exec()、passthru()、shell\_exec()、proc\_open()、和 popen()。
  • open\_basedir 为 /tmp(以便保存会话信息)目录和 web 根目录,以便脚本不能访问这些选定区域外的文件。
  • expose\_php 设置为 off。该功能会向 Apache 头添加包含版本号的 PHP 签名。
  • allow\_url\_fopen 设置为 off。如果你能够注意你代码中访问文件的方式-也就是你验证所有输入参数,这并不严格需要。
  • allow\_url\_include 设置为 off。对于任何人来说,实在没有明智的理由会想要访问通过 HTTP 包含的文件。

一般来说,如果你发现想要使用这些功能的代码,你就不应该相信它。尤其要小心会使用类似 system() 函数的代码-它几乎肯定有缺陷。

启用了这些设置后,让我们来看看一些特定的攻击以及能帮助你保护你服务器的方法。

SQL 注入攻击

由于 PHP 传递到 MySQL 数据库的查询语句是用强大的 SQL 编程语言编写的,就有了某些人通过在 web 查询参数中使用 MySQL 语句尝试 SQL 注入攻击的风险。通过在参数中插入有害的 SQL 代码片段,攻击者会尝试进入(或破坏)你的服务器。

假如说你有一个最终会放入变量 $product 的表单参数,你使用了类似下面的 SQL 语句:

$sql = "select * from pinfo where product = '$product'";

如果参数是直接从表单中获得的,应该使用 PHP 自带的数据库特定转义函数,类似:

$sql = 'Select * from pinfo where product = '"' 
       mysql_real_escape_string($product) . '"';

如果不这样做的话,有人也许会把下面的代码段放到表单参数中:

39'; DROP pinfo; SELECT 'FOO 

那么 $sql 的结果就是:

select product from pinfo where product = '39'; DROP pinfo; SELECT 'FOO' 

由于分号是 MySQL 的语句分隔符,数据库会运行下面三条语句:

select * from pinfo where product = '39'
DROP pinfo
SELECT 'FOO' 

好了,你丢失了你的表。

注意实际上 PHP 和 MySQL 不会运行这种特殊语法,因为 mysql\_query() 函数只允许每个请求处理一个语句。但是,一个子查询仍然会生效。

要防止 SQL 注入攻击,做这两件事:

  • 总是验证所有参数。例如,如果需要一个数字,就要确保它是一个数字。
  • 总是对数据使用 mysql\_real\_escape\_string() 函数转义数据中的任何引号和双引号。

注意:要自动转义任何表单数据,可以启用魔术引号(Magic Quotes)。

一些 MySQL 破坏可以通过限制 MySQL 用户权限避免。任何 MySQL 账户可以限制为只允许对选定的表进行特定类型的查询。例如,你可以创建只能选择行的 MySQL 用户。但是,这对于动态数据并不十分有用,另外,如果你有敏感的用户信息,可能某些人能访问其中一些数据,但你并不希望如此。例如,一个访问账户数据的用户可能会尝试注入访问另一个人的账户号码的代码,而不是为当前会话指定的号码。

防止基本的 XSS 攻击

XSS 表示跨站脚本。不像大部分攻击,该漏洞发生在客户端。XSS 最常见的基本形式是在用户提交的内容中放入 JavaScript 以便偷取用户 cookie 中的数据。由于大部分站点使用 cookie 和 session 验证访客,偷取的数据可用于模拟该用户-如果是一个常见的用户账户就会深受麻烦,如果是管理员账户甚至是彻底的惨败。如果你不在站点中使用 cookie 和 session ID,你的用户就不容易被攻击,但你仍然应该明白这种攻击是如何工作的。

不像 MySQL 注入攻击,XSS 攻击很难预防。Yahoo、eBay、Apple、以及 Microsoft 都曾经受 XSS 影响。尽管攻击不包含 PHP,但你可以使用 PHP 来剥离用户数据以防止攻击。为了防止 XSS 攻击,你应该限制和过滤用户提交给你站点的数据。正是因为这个原因,大部分在线公告板都不允许在提交的数据中使用 HTML 标签,而是用自定义的标签格式代替,例如 [b][linkto]

让我们来看一个如何防止这类攻击的简单脚本。对于更完善的解决办法,可以使用 SafeHTML,本文的后面部分会讨论到。

function transform_HTML($string, $length = null) {
// Helps prevent XSS attacks
    // Remove dead space.
    $string = trim($string);
    // Prevent potential Unicode codec problems.
    $string = utf8_decode($string);
    // HTMLize HTML-specific characters.
    $string = htmlentities($string, ENT_NOQUOTES);
    $string = str_replace("#", "&#35;", $string);
    $string = str_replace("%", "&#37;", $string);
    $length = intval($length);
    if ($length > 0) {
        $string = substr($string, 0, $length);
    }
    return $string;
} 

这个函数将 HTML 特定的字符转换为 HTML 字面字符。一个浏览器对任何通过这个脚本的 HTML 以非标记的文本呈现。例如,考虑下面的 HTML 字符串:

<STRONG>Bold Text</STRONG>

一般情况下,HTML 会显示为:Bold Text

但是,通过 transform\_HTML() 后,它就像原始输入一样呈现。原因是处理的字符串中的标签字符串转换为 HTML 实体。transform\_HTML() 的结果字符串的纯文本看起来像下面这样:

<STRONG>Bold Text</STRONG> 

该函数的实质是 htmlentities() 函数调用,它会将 <、>、和 & 转换为 <>、和 &。尽管这会处理大部分的普通攻击,但有经验的 XSS 攻击者有另一种把戏:用十六进制或 UTF-8 编码恶意脚本,而不是采用普通的 ASCII 文本,从而希望能绕过你的过滤器。他们可以在 URL 的 GET 变量中发送代码,告诉浏览器,“这是十六进制代码,你能帮我运行吗?” 一个十六进制例子看起来像这样:

<a href="http://host/a.php?variable=%22%3e %3c%53%43%52%49%50%54%3e%44%6f%73%6f%6d%65%74%68%69%6e%67%6d%61%6c%69%63%69%6f%75%73%3c%2f%53%43%52%49%50%54%3e"> 

浏览器渲染这个信息的时候,结果就是:

<a href="http://host/a.php?variable="> <SCRIPT>Dosomethingmalicious</SCRIPT>

为了防止这种情况,transform\_HTML() 采用额外的步骤把 # 和 % 符号转换为它们的实体,从而避免十六进制攻击,并转换 UTF-8 编码的数据。

最后,为了防止某些人用很长的输入超载字符串从而导致某些东西崩溃,你可以添加一个可选的 $length 参数来截取你指定最大长度的字符串。

使用 SafeHTML

之前脚本的问题比较简单,它不允许任何类型的用户标记。不幸的是,这里有上百种方法能使 JavaScript 跳过用户的过滤器,并且要从用户输入中剥离全部 HTML,还没有方法可以防止这种情况。

当前,没有任何一个脚本能保证无法被破解,尽管有一些确实比大部分要好。有白名单和黑名单两种方法加固安全,白名单比较简单而且更加有效。

一个白名单解决方案是 PixelApes 的 SafeHTML 反跨站脚本解析器。

SafeHTML 能识别有效 HTML,能追踪并剥离任何危险标签。它用另一个称为 HTMLSax 的软件包进行解析。

按照下面步骤安装和使用 SafeHTML:

  1. http://pixel-apes.com/safehtml/?page=safehtml 下载最新版本的 SafeHTML。
  2. 把文件放到你服务器的类文件夹。该文件夹包括 SafeHTML 和 HTMLSax 功能所需的所有东西。
  3. 在脚本中 include SafeHTML 类文件(safehtml.php)。
  4. 创建一个名为 $safehtml 的新 SafeHTML 对象。
  5. 用 $safehtml->parse() 方法清理你的数据。

这是一个完整的例子:

<?php
/* If you're storing the HTMLSax3.php in the /classes directory, along
   with the safehtml.php script, define XML_HTMLSAX3 as a null string. */
define(XML_HTMLSAX3, '');
// Include the class file.
require_once('classes/safehtml.php');
// Define some sample bad code.
$data = "This data would raise an alert <script>alert('XSS Attack')</script>";
// Create a safehtml object.
$safehtml = new safehtml();
// Parse and sanitize the data.
$safe_data = $safehtml->parse($data);
// Display result.
echo 'The sanitized data is <br />' . $safe_data;
?>

如果你想清理脚本中的任何其它数据,你不需要创建一个新的对象;在你的整个脚本中只需要使用 $safehtml->parse() 方法。

什么可能会出现问题?

你可能犯的最大错误是假设这个类能完全避免 XSS 攻击。SafeHTML 是一个相当复杂的脚本,几乎能检查所有事情,但没有什么是能保证的。你仍然需要对你的站点做参数验证。例如,该类不能检查给定变量的长度以确保能适应数据库的字段。它也不检查缓冲溢出问题。

XSS 攻击者很有创造力,他们使用各种各样的方法来尝试达到他们的目标。可以阅读 RSnake 的 XSS 教程http://ha.ckers.org/xss.html ,看一下这里有多少种方法尝试使代码跳过过滤器。SafeHTML 项目有很好的程序员一直在尝试阻止 XSS 攻击,但无法保证某些人不会想起一些奇怪和新奇的方法来跳过过滤器。

注意:XSS 攻击严重影响的一个例子 http://namb.la/popular/tech.html,其中显示了如何一步一步创建一个让 MySpace 服务器过载的 JavaScript XSS 蠕虫。

用单向哈希保护数据

该脚本对输入的数据进行单向转换,换句话说,它能对某人的密码产生哈希签名,但不能解码获得原始密码。为什么你希望这样呢?应用程序会存储密码。一个管理员不需要知道用户的密码,事实上,只有用户知道他/她自己的密码是个好主意。系统(也仅有系统)应该能识别一个正确的密码;这是 Unix 多年来的密码安全模型。单向密码安全按照下面的方式工作:

  1. 当一个用户或管理员创建或更改一个账户密码时,系统对密码进行哈希并保存结果。主机系统会丢弃明文密码。
  2. 当用户通过任何方式登录到系统时,再次对输入的密码进行哈希。
  3. 主机系统丢弃输入的明文密码。
  4. 当前新哈希的密码和之前保存的哈希相比较。
  5. 如果哈希的密码相匹配,系统就会授予访问权限。

主机系统完成这些并不需要知道原始密码;事实上,原始密码完全无所谓。一个副作用是,如果某人侵入系统并盗取了密码数据库,入侵者会获得很多哈希后的密码,但无法把它们反向转换为原始密码。当然,给足够时间、计算能力,以及弱用户密码,一个攻击者还是有可能采用字典攻击找出密码。因此,别轻易让人碰你的密码数据库,如果确实有人这样做了,让每个用户更改他们的密码。

加密 Vs 哈希

技术上来来说,哈希过程并不是加密。哈希和加密是不同的,这有两个理由:

不像加密,哈希数据不能被解密。

是有可能(但非常罕见)两个不同的字符串会产生相同的哈希。并不能保证哈希是唯一的,因此别像数据库中的唯一键那样使用哈希。

function hash_ish($string) {
    return md5($string);
}

上面的 md5() 函数基于 RSA 数据安全公司的消息摘要算法(即 MD5)返回一个由 32 个字符组成的十六进制串。然后你可以将那个 32 位字符串插入到数据库中和另一个 md5 字符串相比较,或者直接用这 32 个字符。

破解脚本

几乎不可能解密 MD5 数据。或者说很难。但是,你仍然需要好的密码,因为用一整个字典生成哈希数据库仍然很简单。有一些在线 MD5 字典,当你输入 06d80eb0c50b49a509b49f2424e8c805 后会得到结果 “dog”。因此,尽管技术上 MD5 不能被解密,这里仍然有漏洞,如果某人获得了你的密码数据库,你可以肯定他们肯定会使用 MD5 字典破译。因此,当你创建基于密码的系统的时候尤其要注意密码长度(最小 6 个字符,8 个或许会更好)和包括字母和数字。并确保这个密码不在字典中。

用 Mcrypt 加密数据

如果你不需要以可阅读形式查看密码,采用 MD5 就足够了。不幸的是,这里并不总是有可选项,如果你提供以加密形式存储某人的信用卡信息,你可能需要在后面的某个地方进行解密。

最早的一个解决方案是 Mcrypt 模块,这是一个用于允许 PHP 高速加密的插件。Mcrypt 库提供了超过 30 种用于加密的计算方法,并且提供口令确保只有你(或者你的用户)可以解密数据。

让我们来看看使用方法。下面的脚本包含了使用 Mcrypt 加密和解密数据的函数:

<?php
$data = "Stuff you want encrypted";
$key = "Secret passphrase used to encrypt your data";
$cipher = "MCRYPT_SERPENT_256";
$mode = "MCRYPT_MODE_CBC";
function encrypt($data, $key, $cipher, $mode) {
// Encrypt data
return (string)
            base64_encode
                (
                mcrypt_encrypt
                    (
                    $cipher,
                    substr(md5($key),0,mcrypt_get_key_size($cipher, $mode)),
                    $data,
                    $mode,
                    substr(md5($key),0,mcrypt_get_block_size($cipher, $mode))
                    )
                );
}
function decrypt($data, $key, $cipher, $mode) {
// Decrypt data
    return (string)
            mcrypt_decrypt
                (
                $cipher,
                substr(md5($key),0,mcrypt_get_key_size($cipher, $mode)),
                base64_decode($data),
                $mode,
                substr(md5($key),0,mcrypt_get_block_size($cipher, $mode))
                );
}
?>

mcrypt() 函数需要几个信息:

  • 需要加密的数据
  • 用于加密和解锁数据的口令,也称为键。
  • 用于加密数据的计算方法,也就是用于加密数据的算法。该脚本使用了 MCRYPT\_SERPENT\_256,但你可以从很多算法中选择,包括 MCRYPT\_TWOFISH192MCRYPT\_RC2MCRYPT\_DES、和 MCRYPT\_LOKI97
  • 加密数据的模式。这里有几个你可以使用的模式,包括电子密码本(Electronic Codebook) 和加密反馈(Cipher Feedback)。该脚本使用 MCRYPT\_MODE\_CBC 密码块链接。
  • 一个 初始化向量-也称为 IV 或者种子,用于为加密算法设置种子的额外二进制位。也就是使算法更难于破解的额外信息。
  • 键和 IV 字符串的长度,这可能随着加密和块而不同。使用 mcrypt\_get\_key\_size()mcrypt\_get\_block\_size() 函数获取合适的长度;然后用 substr() 函数将键的值截取为合适的长度。(如果键的长度比要求的短,别担心,Mcrypt 会用 0 填充。)

如果有人窃取了你的数据和短语,他们只能一个个尝试加密算法直到找到正确的那一个。因此,在使用它之前我们通过对键使用 md5() 函数增加安全,就算他们获取了数据和短语,入侵者也不能获得想要的东西。

入侵者同时需要函数,数据和口令,如果真是如此,他们可能获得了对你服务器的完整访问,你只能大清洗了。

这里还有一个数据存储格式的小问题。Mcrypt 以难懂的二进制形式返回加密后的数据,这使得当你将其存储到 MySQL 字段的时候可能出现可怕错误。因此,我们使用 base64encode()base64decode() 函数转换为和 SQL 兼容的字母格式和可检索行。

破解脚本

除了实验多种加密方法,你还可以在脚本中添加一些便利。例如,不用每次都提供键和模式,而是在包含的文件中声明为全局常量。

生成随机密码

随机(但难以猜测)字符串在用户安全中很重要。例如,如果某人丢失了密码并且你使用 MD5 哈希,你不可能,也不希望查找回来。而是应该生成一个安全的随机密码并发送给用户。为了访问你站点的服务,另外一个用于生成随机数字的应用程序会创建有效链接。下面是创建密码的一个函数:

<?php
 function make_password($num_chars) {
    if ((is_numeric($num_chars)) &&
        ($num_chars > 0) &&
        (! is_null($num_chars))) {
        $password = '';
        $accepted_chars = 'abcdefghijklmnopqrstuvwxyz1234567890';
        // Seed the generator if necessary.
        srand(((int)((double)microtime()*1000003)) );
        for ($i=0; $i<=$num_chars; $i++) {
            $random_number = rand(0, (strlen($accepted_chars) -1));
            $password .= $accepted_chars[$random_number] ;
        }
        return $password;
     }
}
?> 

使用脚本

make\_password() 函数返回一个字符串,因此你需要做的就是提供字符串的长度作为参数:

<?php
$fifteen_character_password = make_password(15);
?> 

函数按照下面步骤工作:

  • 函数确保 $num\_chars 是非零的正整数。
  • 函数初始化 $accepted\_chars 变量为密码可能包含的字符列表。该脚本使用所有小写字母和数字 0 到 9,但你可以使用你喜欢的任何字符集合。(LCTT 译注:有时候为了便于肉眼识别,你可以将其中的 0 和 O,1 和 l 之类的都去掉。)
  • 随机数生成器需要一个种子,从而获得一系列类随机值(PHP 4.2 及之后版本中并不需要,会自动播种)。
  • 函数循环 $num\_chars 次,每次迭代生成密码中的一个字符。
  • 对于每个新字符,脚本查看 $accepted\_chars** 的长度,选择 0 和长度之间的一个数字,然后添加 **$accepted\_chars 中该数字为索引值的字符到 $password。
  • 循环结束后,函数返回 $password

许可证

本篇文章,包括相关的源代码和文件,都是在 The Code Project Open License (CPOL) 协议下发布。


via: http://www.codeproject.com/Articles/363897/PHP-Security

作者:SamarRizvi 译者:ictlyh 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

Crossroads 是一个独立的服务,它是一个用于Linux和TCP服务的开源负载均衡和故障转移实用程序。它可用于HTTP,HTTPS,SSH,SMTP 和 DNS 等,它也是一个多线程的工具,在提供负载均衡服务时,它可以只使用一块内存空间以此来提高性能。

首先来看看 XR 是如何工作的。我们可以将 XR 放到网络客户端和服务器之间,它可以将客户端的请求分配到服务器上以平衡负载。

如果一台服务器宕机,XR 会转发客户端请求到另一个服务器,所以客户感觉不到停顿。看看下面的图来了解什么样的情况下,我们要使用 XR 处理。

Install XR Crossroads Load Balancer

安装 XR Crossroads 负载均衡器

这里有两个 Web 服务器,一个网关服务器,我们将在网关服务器上安装和设置 XR 以接收客户端请求,并分发到服务器。

XR Crossroads 网关服务器:172.16.1.204

Web 服务器01:172.16.1.222

Web 服务器02:192.168.1.161

在上述情况下,我们网关服务器(即 XR Crossroads)的IP地址是172.16.1.204,webserver01 为172.16.1.222,它监听8888端口,webserver02 是192.168.1.161,它监听端口5555。

现在,我们需要的是均衡所有的请求,通过 XR 网关从网上接收请求然后分发它到两个web服务器已达到负载均衡。

第1步:在网关服务器上安装 XR Crossroads 负载均衡器

1. 不幸的是,没有为 crossroads 提供可用的 RPM 包,我们只能从源码安装。

要编译 XR,你必须在系统上安装 C++ 编译器和 GNU make 组件,才能避免安装错误。

# yum install gcc gcc-c++ make

接下来,去他们的官方网站(https://crossroads.e-tunity.com)下载此压缩包(即 crossroads-stable.tar.gz)。

或者,您可以使用 wget 去下载包然后解压在任何位置(如:/usr/src/),进入解压目录,并使用 “make install” 命令安装。

# wget https://crossroads.e-tunity.com/downloads/crossroads-stable.tar.gz
# tar -xvf crossroads-stable.tar.gz
# cd crossroads-2.74/
# make install

Install XR Crossroads Load Balancer

安装 XR Crossroads 负载均衡器

安装完成后,二进制文件安装在 /usr/sbin 目录下,XR 的配置文件在 /etc 下名为 “xrctl.xml” 。

2. 最后一个条件,你需要两个web服务器。为了方便使用,我在一台服务器中创建两个 Python SimpleHTTPServer 实例。

要了解如何设置一个 python SimpleHTTPServer,请阅读我们此处的文章 使用 SimpleHTTPServer 轻松创建两个 web 服务器.

正如我所说的,我们要使用两个web服务器,webserver01 通过8888端口运行在172.16.1.222上,webserver02 通过5555端口运行在192.168.1.161上。

XR WebServer 01

XR WebServer 01

XR WebServer 02

XR WebServer 02

第2步: 配置 XR Crossroads 负载均衡器

3. 所需都已经就绪。现在我们要做的就是配置xrctl.xml 文件并通过 XR 服务器接受来自互联网的请求分发到 web 服务器上。

现在用 vi/vim 编辑器打开xrctl.xml文件。

# vim /etc/xrctl.xml

并作如下修改。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system>
<uselogger>true</uselogger>
<logdir>/tmp</logdir>
</system>
<service>
<name>Tecmint</name>
<server>
<address>172.16.1.204:8080</address>
<type>tcp</type>
<webinterface>0:8010</webinterface>
<verbose>yes</verbose>
<clientreadtimeout>0</clientreadtimeout>
<clientwritetimout>0</clientwritetimeout>
<backendreadtimeout>0</backendreadtimeout>
<backendwritetimeout>0</backendwritetimeout>
</server>
<backend>
<address>172.16.1.222:8888</address>
</backend>
<backend>
<address>192.168.1.161:5555</address>
</backend>
</service>
</configuration>

Configure XR Crossroads Load Balancer

配置 XR Crossroads 负载均衡器

在这里,你可以看到在 xrctl.xml 中配置了一个非常基本的 XR 。我已经定义了 XR 服务器在哪里,XR 的后端服务和端口及 XR 的 web 管理界面是什么。

4. 现在,你需要通过以下命令来启动该 XR 守护进程。

# xrctl start
# xrctl status

Start XR Crossroads

启动 XR Crossroads

5. 好的。现在是时候来检查该配置是否可以工作正常了。打开两个网页浏览器,输入 XR 服务器的 IP 地址和端口,并查看输出。

Verify Web Server Load Balancing

验证 Web 服务器负载均衡

太棒了。它工作正常。是时候玩玩 XR 了。(LCTT 译注:可以看到两个请求分别分配到了不同服务器。)

6. 现在可以通过我们配置的网络管理界面的端口来登录到 XR Crossroads 仪表盘。在浏览器输入你的 XR 服务器的 IP 地址和你配置在 xrctl.xml 中的管理端口。

http://172.16.1.204:8010

XR Crossroads Dashboard

XR Crossroads 仪表盘

看起来像上面一样。它容易理解,用户界面​​友好,易于使用。它在右上角显示每个服务器能容纳多少个连接,以及关于接收该请求的附加细节。你也可以设置每个服务器承担的负载量,最大连接数和平均负载等。

最大的好处是,即使没有配置文件 xrctl.xml,你也可以做到这一点。你唯一要做的就是运行以下命令,它就会把这一切搞定。

# xr --verbose --server tcp:172.16.1.204:8080 --backend 172.16.1.222:8888 --backend 192.168.1.161:5555

上面语法的详细说明:

  • -verbose 将显示命令执行后的信息。
  • -server 定义你在安装包中的 XR 服务器。
  • -backend 定义你需要平衡分配到 Web 服务器的流量。
  • tcp 说明我们使用 TCP 服务。

欲了解更多详情,有关文件及 CROSSROADS 的配置,请访问他们的官方网站: https://crossroads.e-tunity.com/.

XR Corssroads 使用许多方法来提高服务器性能,避免宕机,让你的管理任务更轻松,更简便。希望你喜欢此文章,并随时在下面发表你的评论和建议,方便与我们保持联系。


via: http://www.tecmint.com/setting-up-xr-crossroads-load-balancer-for-web-servers-on-rhel-centos/

作者:Thilina Uvindasiri 译者:strugglingyouth 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

简介

Linux From Scratch,简称 LFS,不同于其它的 Linux 发行版,它是一种给使用者指导建议,由使用者自行从头开始自己构建的发行版。LFS 发行版及其衍生版本,都由其同名的手册提供了完整的指导建议。

《Linux From Scratch》(LFS)是由 Gerard Beekmans 等人编写的。这本书可以从在Linux From Scratch网站上免费下载到,当前最新的版本为 8.1。

尽管目标是安装一个与现有发行版毫无关系的系统,安装LFS仍然不能无中生有,而必须要有一个可以编译软件包的运行中的Linux系统。这个系统一般称为宿主系统。在宿主操作系统上安装LFS,需要的基本步骤如下:

  • 准备新分区(第二章)
  • 软件包与补丁(第三章)
  • 最后的准备(第四章)
  • 构建临时文件系统(第五章)
  • 安装基本的系统软件(第六章)
  • 基本系统配置(第七章)
  • 让 LFS 系统可引导(第八章)

LFS 的官方网站是: http://www.linuxfromscratch.org/

相关项目

该项目有很多相关子项目:

Beyond Linux From Scratch(BLFS)

标准LFS仅仅安装了足够让系统启动的基本软件,以及使新系统能够编译新软件包的开发工具。BLFS包括了更多的软件包,且都有相应指导。

Crosss Linux From Scratch(CLFS)

为需要进行交叉编译(即在一个平台上编译另一个平台的代码)的用户提供指导,正式版本为1.0,另有两个变种

  • CLFS Sysroot 采用Sysroot的方法来进行编译,好处是软件包的编译次数可以减少,坏处是不能支持在编译后对软件进行测试,必须要启动到目标平台上才能测试。
  • CLFS Embedded 一般用于极小系统以及嵌入式系统。为此,它使用uclibc而不是一般LFS使用的glibc

Automated Linux From Scratch(ALFS)

标准LFS只是一本书,用户需要根据书上的指引下载软件包并手动输入指令进行编译。ALFS子项目提供了把这一切自动化的脚本。

Hardened Linux From Scratch(HLFS)

这个子项目致力于打造在安全性上无懈可击的Linux系统。

当前版本

LFS 的当前版本是 8.1,分为采用 systemd 的版本和不采用的版本。

手册

Systemd 版本:

Systemd 版本(简体中文翻译版本):

LCTT 对 LFS 7.1 systemd 版本进行了翻译,并且 LFS 官方网站收录了相应链接:

非 Systemd 版本:

注:部分资料来自维基百科。

简介

Fedora Linux(第七版以前为 Fedora Core)是较具知名度的 Linux 发布包之一,由 Fedora 项目社区开发、红帽公司赞助,目标是创建一套新颖、多功能并且自由(开放源代码)的操作系统。

Fedora 基于 Red Hat Linux,在Red Hat Linux终止发布后,红帽公司项目以 Fedora 来取代 Red Hat Linux 在个人领域的应用,而另外发布的 Red Hat Enterprise Linux(Red Hat企业版Linux)则取代 Red Hat Linux 在商业应用的领域。

Fedora 对于用户而言,是一套功能完备、更新快速的免费操作系统。而对赞助者 Red Hat 公司而言,它是许多新技术的测试平台,被认为可用的技术最终会加入到 Red Hat Enterprise Linux 中。

Fedora 大约每六个月发布新版本,目前 Fedora 最新的版本是Fedora 27。

官方网站: http://fedoraproject.org/

下载

Fedora 27 Workstation Live

Fedora Workstation Live 镜像让您可以为自己电脑制作完整的立即可用的 Fedora Workstation 系统介质。您可以使用 Live 镜像测试、体验 Fedora,同时无需改动硬盘内容。当您满意之后,您可以从 Live 镜像安装 Fedora 到您的硬盘。要使用该镜像,您需要可创建或刻录 DVD 的驱动器或者至少跟镜像大小一样的 USB 闪存盘。版本 27 之后就不再提供 32 位的 Live 安装镜像了,需要安装 32 位的 27 版本只能通过网络安装。

  • Intel & AMD/ 兼容 PC 64 位,适用于 64-bit 位 PC 点此下载

Fedora 27 Server

Fedora Server 安装镜像可让您为计算机制作介质以便引导安装程序将 Fedora Server 直接安装到您的硬盘。

  • Intel & AMD/ 兼容 PC 64 位,适用于 64-bit 位 PC 点此下载

发行

Fedora 项目以不同方式发行 Fedora:

  • Fedora DVD/CD – 包含了所有主要软件包的DVD或CD套装;
  • Live镜像 – CD或DVD大小的光盘镜像,可用于创建Live CD或从USB设备启动,并可选安装到硬盘;
  • 最小CD – 用于通过HTTP,FTP或NFS安装。

您可以通过 Fedora Live USB Creator 或 UNetbootin 创建 Live USB 版本的 Fedora。

同时,Fedora 项目发布自定义的 Fedora 版本,称作 Fedora spins。这些版本包含特定的软件包集合,还有各种桌面环境,如 KDE Plasma、Xfce、LXDE、MATE和Cinnamon,以满足特定种类的用户之需要。Fedora spins 由一些对 Fedora 有特殊兴趣的小组开发。

Enterprise Linux额外软件包 Extra Packages for Enterprise Linux,EPEL 是由来自 Fedora Project 的志愿者发起的社区力量,为了创建由高质量的附加软件组成的、用于补足 RHEL 和其他兼容版本的软件仓库。

Fedora 主要使用 RPM 软件包管理系统。Fedora 同样提供图形界面(例如pirut,pup和puplet),用于在更新可用时提供视觉通知。apt-rpm 是 yum 的替代品,对于Debian类发行版的用户来说可能更熟悉。这里,APT被用于管理软件包。 额外的软件仓库(EPEL)可以被添加到 Fedora,以便安装 Fedora 软件仓库未提供的软件包。

测试版

Fedora Project在发布每一个稳定版本之前,会先发布三次测试版本让用户测试并协助改进。Fedora 7 由于要合并 Core 和 Extra,引入了第四个测试版。

Fedora 另外还有个用来放置不稳定(Bleeding-Edge)软件的包库称为Rawhide,开发中的软件包会先发布在 Rawhide,然后再转移至 Fedora 包库。Rawhide 更新相当频繁,并不适合一般工作用途,但还是有些开发者和测试者用来作主要的工作系统。

当前版本

最新的Fedora版本为 27,有“Server”、“Cloud”和“Workstation”三个版本,发布于 2017 年 11 月 14 日。 详情说明请浏览官方的 Fedora 27 Release Note

特色

与Red Hat Linux的相似度

Fedora 承继了 Red Hat Linux 的安装接口Anaconda、桌面环境(同时包含 Gnome 和 KDE)、包管理器RPM、多国语系支持以及许多设置工具,所以习惯于使用 Red Hat 操作系统的用户会感到相当熟悉,也因为如此,Fedora 用户在转移至RHEL、CentOS 等系统时不会面临太多差异。

引入新技术

因其趋近半年一次的发布周期,Fedora 在引入新技术的部分颇为快速,通常每一个版本都会引入最新版的 Xorg、Gnome 以及 KDE。

自由软件的推广

Fedora Project 在自由软件的推广上有积极的作为。其内置自由软件的 GNU Java 运行环境 libgcj 可成功运行 Eclipse 等Java 软件,而不需使用 Oracle 的 Java 运行环境。另外 Fedora 官方也不支持专利封闭的多媒体格式(如MP3等),并建议用户支持诸如 Ogg 等开放的多媒体格式。

Fedora Core 5 引入了 Mono 项目,Mono 是开放源代码且跨平台的 .NET 运行环境与开发工具。

软件包

Fedora 使用yum工具来协助RPM包的管理,可以有效避免相依性地狱的问题。并且,用户可以利用yum来方便获取原先Fedora 因专利权因素所不包含的功能,例如:MP3播放支持、DVD视频支持以及NTFS文件系统支持等功能。Fedora 21 及其之前的版本默认使用 yum,而在 Fedora 22 及之后的版本默认使用 DNF 。DNF 由 yum 分支出来,DNF 将会取代老旧的 yum。

Fedora的官方包库在收纳上有其多样性,例如 ClamAV(杀毒软件)与 Wine(Windows软件转译器)都可在官方包库中获取,另外也包含许多开放源代码的游戏软件。livna 和 freshrpms 等社区也提供了和官方包库兼容的第三方包,用户可从中获取 NVIDIA 和 ATI 的 3D 显卡驱动程序或是 VLC、MPlayer 等播放软件。

多平台支持

Fedora 官方支持 x86、x86-64 以及 PowerPC 处理器,游戏机方面,Fedora Core 5、Fedora Core 6、Fedora 7 也已成功安装在 PlayStation 3 上。

简化目录结构

一直以来 unix 及类 unix 系统的目录结构对于很多人显得晦涩难懂,Fedora 计划简化其目录结构,将二进制文件集中放在 /usr/bin,将库文件集中到/usr/lib 和 /usr/lib64,而对于原本同样用于存储二进制文件的 /bin 和 /sbin 将以连接的形式指向 /usr/bin,同样的 /lib /lib64 也会以连接形式指向对应目录。示意如下:

/  
|-- etc 
|-- usr
|-- bin
|-- lib
|-- lib64
|-- run
|-- var
|-- bin -> usr/bin
|-- sbin -> usr/bin
|-- lib -> usr/lib
|-- lib64 -> usr/lib64

历史

Fedora版本命名规则:第n版与第n+1版有继承关系,但与第n+2版没有相同继承关系。

版本列表

名称版本发布日期终止日期内核版本XorgGNOMEKDE
Fedora272017-11-14-4.1311.03.26Plasma5.11.3
262017-7-11-4.11-3.24-
252016-11-222017-12-124.8-3.22-
242016-6-212017-8-84.5-3.20-
232015-11-32016-12-204.2-3.18-
222015-5-262016-7-194.01.173.16Plasma5.3
Applications 15.04
212014-12-92015-12-13.161.163.144.14
20(Heisenbug)2013-12-172015-6-233.111.143.104.11
19(Schrödinger's Cat)2013-7-22015-1-63.91.143.84.10
18(Spherical Cow)2013-1-152014-1-43.61.133.64.9
17(Beefy Miracle)2012-5-292013-2-123.3.41.123.44.8
16(Verne)2011-11-82013-2-123.1.01.11.13.2.14.7.3
15(Lovelock)2011-5-242012-6-262.6.381.10.13.04.6
14(Laughlin)2010-11-22011-12-82.6.351.9.12.324.5.2
13(Goddard)2010-5-252011-6-242.6.331.8.02.304.4.2
12(Constantine)2009-11-172010-12-22.6.311.7.12.28.04.3.2
11(Leonidas)2009-6-92010-6-252.6.29.41.62.26.14.2.2
10(Cambridge)2008-11-252009-12-182.6.271.5.22.24.14.1.2
9(Sulphur)2008-5-132009-7-102.6.251.4.992.22.14.0.3
8(Werewolf)2007-11-82009-1-72.6.23.11.3.02.20.13.5.8
7(Moonshine)2007-5-312008-6-132.6.211.3.02.18.03.5.6
Fedora Core6(Zod)2006-10-242007-12-72.6.181.1.12.16.03.5.4
5(Bordeaux)2006-3-202007-7-22.6.151.0.12.14.03.5.1
4(Stentz)2005-6-132006-8-72.6.116.8.22.10.03.4.0
3(Heidelberg)2004-11-82006-1-162.6.96.8.12.8.13.3.0
2(Tettnang)2004-5-182005-4-112.6.56.7.02.6.03.2.2
1(Yarrow)2003-11-52004-9-202.4.194.3.0 (XFree86)2.4.03.1.4

注:由于 Feodra 每个版本在整个支持周期内会更新上述程序,所以上述表格的程序版本只是该本版发布初始的软件版本

注:部分资料来自维基百科。