linuxjava环境变量:如何设定执行Java的Linux安全环境



企业 专家 Dennis Sosnoski 从 技术如何适合 Linux 来开始阐述他观点然后给出在 Linux 上地设定 Tomcat Java servlet 引擎点建议

Linux 平台和 Java 平台有着久远但有经常经历曲折关系建置高效能虚拟机器同时又要跟上日益增长核心 Java API 集合这样做所带来复杂性在很大程度上使开发 Java 平台开放来源代码「Clean Room」实作早期行动困难重重Java 技术特许实作最终可用于 Linux但这些实作并不是开放来源代码因此大多数 Linux 分发版没有包括该特许实作

尽管有这些困难Java 平台还是提供了许多好处从而导致在 Linux 上越来越多地使用该特许实作尤其是对于应用在本文中我回顾了 Java 平台给服务器应用带来优点然后研究了在 Linux 上简单且地部署 Java 服务所涉及问题作为个实际范例我将讨论设定 Apache Software Foundation 广泛使用 Tomcat Java servlet 引擎详细信息以用于独立作业

为什么使用 Java 平台?

有许多原因可以解释为什么 Java 平台成为基于服务器商业应用广为接受选择我将主要讨论我认为对于该环境至关重要 3个原因︰跨平台兼容性、受管执行时环境和易于开发

Java 应用提供了跨多种操作系统和硬件平台 2进制兼容性对于非 GUI 服务器应用尤其是这样在此类别应用通常在实际目标系统中需要执行非常少测试工作人员可以在任何他们喜欢平台上进行编码和除错同时仍可以将这些应用部署到他们也许不能直接控制环境中

Java 虚拟机器(Java Virtual MachineJVM)环境执行时特性以几种方式来加强安全性最显著方面的是严格类别型检查、边界检查和自动垃圾收集组合彻底防止了最具破坏性形式服务器代码攻击︰缓冲区溢位、重复释放和游离指针Java 语言早期用于 applet经过不断发展该语言还有个完善系统用于对那些已确信存在安全性风险设施进行细微存取控制这些思路方法可供独立应用选择使用但它们已建置在许多 Java 服务架构中

这些执行时安全特性还提供了用 Java 语言开发便利性要对便利性这类别问题作任何精确测量是困难但大多数具有诸如 C 和 C 的类别语言背景而转向 Java 工作人员都承认在转变的后他们生产力提高了其中部分是在编译时和执行时严格执行类别型确定以及自动内存管理简单性个原因是为 Java 平台开发标准 API 扩充集合这些 API 对于新工作人员可能是个重大挑战但是旦学会了API 会为各种企业需求提供优秀跨平台支持

当然对于某些应用而言Java 平台可能是个糟糕选择尽管 JVM 体系结构在持续改进但 Java 应用通常会比使用相同算法 C 或 C 应用执行得稍微慢根据我经验和测试我估计这个速度差异对于在特许 JVM 上执行大多数服务器应用来说大约是在 20% 到 50% 范围内然而这很大程度上取决于代码质量和独立相比在这些 JVM 上执行 Java 应用还忍受着比较慢启动但是这对于长时间执行服务器应用通常并不是个重大问题在大多数情况中降低效能和较慢启动祇是为获得 Java 平台增强安全性和更快速开发优点所付出微小代价

开放来源码替代选择

除了标准特许 JVM(免费使用但是来源码受到限制;可用于 Sun、IBM、BEA 和 Blackdown 组织 Linux)的外对于 Linux 还有其它几个替代选择这些选择包括「Clean Room」开放来源码 JVM 实作其中使用最广泛可能是 Kaffe(在许多 Linux 分发版中都包括它)Kaffe 是个非常有意义项目它已经完成了些令人惊讶工作但它只能提供和目前特许 JVM 有限兼容性因此它通常无法使用于本文所关注企业类别型服务器应用

用于 Java 本机代码编译器开放来源码工作也有几个替代选择这里最重要项目是 GNU 编译器集(GNU Compiler Collection) GCJ.使用诸如 CGJ 的类别本机代码编译器会将独立于平台 Java 字节码在其执行的前转换成特定于平台代码(这和在 JVM 中执行成对比在 JVM 中执行通常在执行时将字节码转换成特定于平台代码)

本机代码编译显示出它极有可能成为种避免在 JVM 中执行 Java 应用启动较慢思路方法但是使用这种思路方法编译器通常都不能和当代特许 JVM 稳定状态效能相匹配如果 Java 应用使用 Java 平台动态特性(如使用反射来存取字段或加载在执行时选择类别)这种情况尤其突出根据所使用实作和编译选项本机代码编译也许还会削弱 Java 平台许多执行时安全特性最后由于许可证问题许多 Java API 不能和已编译本机代码起使用由于这些限制本机代码编译目前还不是 Java 平台服务器应用个好选择

如何样?

和 Java 执行时环境有许多共同点个替代思路方法是 Microsoft 语言和相关公共语言执行时(Common Language RuntimeCLR) 是 Java 语言关系紧密衍生物CLR 可能容许 C# 在许多平台上使用CLR 还提供了 JVM 许多执行时安全特性(尽管有严重削弱安全保证逃离出口)Microsoft 实作还支持预编译成本机代码选项以获得更快速启动这和 GCJ 对 Java 字节码所做工作相同当然Linux 使用者并不能直接使用这项功能 只适用于 系统

Mono Project 正致力于为多种 Linux 产品建置「CLean Room」开放来源码 C# 和等价于 CLR 产品现在该项目中 C# 编译器已开发完成而且还完成了大部分 CLRMicrosoft 已发布将它用于标准化但是无论从效能还是功能角度来看在它成为合理 Java 平台替代选择的前还有许多工作要做CLR 只包括了和 Java 核心类别库等价基本内容在可以将它看作是企业软件Software开发合理选项的前还需要用许多额外 API 来补充它

Mono Project 正在致力于开发 CLR 以外 .Net 其它部分移植如果这些移植成功了 ─ 并且如果 Microsoft 不对 .Net 这些部分强加它专利权 ─ 那么它们会有助于满足 C# 成为 Linux 上服务器软件Software开发可靠平台需要但要使那些假设成为现实还需要做很多工作同时Java 本机代码编译器和开放来源码 JVM 向那些确实想要避免使用特许 JVM 并可以忍受有限功能性使用者提供了比较稳定替代选择

Apache Tomcat

最普遍存在 Java 平台服务器应用是 Apache Tomcat.Tomcat 是基于最初由 Sun 捐赠来源码开放来源码项目它是个 HTTP 服务器是 Sun 透过 Java Community Process 开发、对广泛使用 servlet 和 JavaServer Page(JSP)技术正式参考实作我将在本文中使用 Tomcat 作为样本 Java 应用将其部署成 Linux 上个服务如果您想要尝试自己执行 Tomcat那么您将需要在系统上安装 Java 开发工具箱(Java Development KitJDK)而不是安装更小 Java 执行时环境(Java Runtime EnvironmentJRE)

servlet 和 JSP 技术用于建构 HTTP 服务器应用虽然 servlet 技术中加入了许多特性(包括存取安全性、Session管理和执行绪控制)但它本身祇是粗略地等价于为快速直接 Java 语言呼叫而定制 CGI 接口JSP 技术提供了种处理动态生成 HTML 页面简便思路方法这些 HTML 页面被直接编译成 servlet 以用于快速执行时作业

在这两种技术的外Tomcat 还提供了其它许多特性凭它本身效能它实际上是全功能 Web 服务器但它通常在 Linux 系统上和 Apache Web 服务器前端共同使用Apache 向 Tomcat 提供了许多进阶效能以适合静态内容对于静态内容所占比例比较高且使用率很高 Web 应用Apache 前端非常有用但对于许多简单 Web 应用就没必要使用它了当更易于组态和管理时单独执行 Tomcat 就可提供足够效能(至少对于以前没有使用过 Apache 工作人员来说是这样)

连接埠难题

单独执行 Tomcat 个大问题是它无法存取标准 HTTP 连接埠 80除非是作为 root 使用者执行作为 root 使用者执行服务器应用想法通常并不是上串流公司所讨论问题因此我将完全放弃这个想法﹗使用除 80 以外连接埠是个更好选择(例如Tomcat 缺省连接埠 8080)这通常适用于测试但当使用者正在存取服务时它会导致杂乱 URL需要在请求中清楚地介绍说明连接埠号使用非标准连接埠还意味着如果需要外部存取就需要重新组态所有

xinetd 解决方案

幸好Linux 支持些利用 Tomcat(或任何其它使用者方式应用)处理连接端口 80 请求简便方式种常用方式是透过 xinetd.xinetd 是带有广泛存取控制和日志记录支持因特网服务守护它还拥有方便重新导向特性重新导向让您将系统组态成接受个连接埠上进入请求然后将请求传递到另个连接埠或者甚至另个 IP 地址进行处理

如果您想要在系统上设定 Tomcat 以处理连接埠 80 请求就需要加入 xinetd 组态文件来实作这假设按般在正常路径上安装了 xinetd那么您可以透过对 /etc/xinetd.d 目录加入个文件(以 root 使用者身份)来执行这作业清单 1 提供了用于 Tomcat 个样本组态文件

清单 1. xinetd 重新导向组态

# Redirects any requests _disibledevent=> protocol = tcp

user = root

wait = no

port = 80

redirect = localhost 8080

disable = no

}

在加入了组态文件的后需要重新启动 xinetd 来真正活化重新导向在大多数 Linux 安装上透过以 root 使用者身份执行以下指令来重新启动 xinetd︰

/sbin/service xinetd restart

祇要将组态文件放在 /etc/xinetd.d 目录中当重新启动系统时重新导向就会自动启动如果没有将 Tomcat 设定成自动启动那么在启动 Tomcat 的前会拒绝进入请求

iptables 解决方案

xinetd 是处理请求重新导向种好思路方法但它执行了个处理序以在连接端口的间实际转信数据这确实增加了些开销最新 Linux 内核版本透过使用 iptables 来支持种更好设定重新导向思路方法iptables 和 xinetd 区别的处在于它是个真正内核组件因此它可以避免 xinetd 思路方法增加开销使用 iptables 缺点是它可能比 xinetd 更难以组态而且它只可用于相当新内核版本

您需要执行支持 iptables 2.4.x 或更新内核以便使用我在这里描述技术组态和设定 iptables 是个确信由几篇文章来单独描述主题所以我不打算在这里尝试讨论该主题如果对 iptables 入门需要帮助请阅读 Linux 分发版手册要快速检查 iptables 是否在您系统上执行尝试以 root 使用者身份执行︰

/sbin/service iptables status

如果它正在执行您将会在控制台上看到表和链清单

iptables 使用几个区别表和封包链来处理规则为了将进入 HTTP 请求从连接端口 80 重新导向到系统中个连接埠您将要使用 nat 表(表示网络地址转换Network Address Translation)和 PREROUTING 链清单 2 提供了要执行实际指令(以 root 使用者身份)以便于加入条处理这请求规则这条规则作用是将进入包目标连接端口 80 修改成目标连接端口 8080因此祇有在您没有阻止从外部使用连接埠 8080 时这条规则才会正确工作旦执行了该指令您就应该能够立即处理进入请求

清单 2. iptables 重新导向规则

/sbin/iptables -t nat \

-A PREROUTING -j REDIRECT -p tcp \

——destination-port 80:80 ——to-ports 8080

/sbin/service iptables save

以便于储存目前 iptables 组态









自动启动 Tomcat

当执行诸如 Tomcat 的类别 Java 服务时个问题是当系统启动时如何自动启动该应用以及当系统关机时如何自动停止它(换句话说将它当作守护执行)经验丰富 Linux 使用者已经知道怎样做但如果您还是个 Linux 新手以下就是些基础知识

如果您就在您个人系统上执行它并且想要使用和直接执行 Tomcat 对 Tomcat 文件和目录存取权那么您可以用您自己使用者名称来设定它但是通常个比较好想法是︰为将要作为守护执行任何设定个单独使用者要针对 Tomcat 执行这作业以 root 使用者身份执行︰

/usr/sbin/useradd tomcat

这将建立个名为 tomcat 使用者账户并建立个用于 Tomcat 安装主目录 /home/tomcat.所建立主目录所有者是 tomcat 使用者而且通常只容许这个使用者存取(当然还有 root 使用者)如果想要从其它账户存取 Tomcat 安装可以将许可权变更成包括组存取权并将 tomcat 组新增到这些其它账户

总的要将 Tomcat 当作守护执行需要将服务组态文件新增到 /etc/init.d 目录中而您可能要将该文件命名为「tomcat」清单 3 提供了该文件样本这假设了 Tomcat 安装在 /home/tomcat 下并且该位置中有两个 shell 指令码文件用于处理启动和停止服务器(tcstart.sh 和 tcstop.sh)在执行实际 Tomcat 启动或停止指令码的前需要使用这些文件来设定 Tomcat 所需环境变量(包括 JAVA_HOME 和 JDK_HOME)

清单 3. Tomcat 服务定义

#!/bin/bash

#

# tomcat Starts Tomcat Java server.

#

#

# chkconfig: 345 88 12

# description: Tomcat is the server for Java servlet applications.

### BEGIN INIT INFO

# Provides: $tomcat

### END INIT INFO

# Source function library.

/etc/init.d/functions

[ -f /home/tomcat/tcstart.sh ] || exit 0

[ -f /home/tomcat/tcstop.sh ] || exit 0

RETVAL=0

umask 077

start() {

echo -n $"Starting Tomcat Java server: "

daemon su -c /home/tomcat/tcstart.sh tomcat

echo

$RETVAL

}

stop() {

echo -n $"Shutting down Tomcat Java server: "

daemon su -c /home/tomcat/tcstop.sh tomcat

echo

$RETVAL

}

restart() {

stop

start

}

"$1" in

start)

start

;;

stop)

stop

;;

restart|reload)

restart

;;

*)

echo $"Usage: $0 {start|stop|restart}"

exit 1

esac

exit $?

以下是个样本 tcstart.sh可以修改它来适合您安装

清单 4. 样本 tcstart.sh

#!/bin/bash

export JDK_HOME=/usr/java/jdk

export JAVA_HOME=/usr/java/jdk

#run the startup script from Tomcat ation

/home/tomcat/server/bin/startup.sh

chroot︰最大安全性监狱

对于真正偏执狂还可能进步讨论保护 Java 语言服务当该服务提供对本地文件系统某种形式存取权时这尤其有用JVM 执行时安全性特性并不能阻止已经有权存取文件系统应用存取除了使用者专用文件的外文件在 Tomcat 情况中文件存取是它作为 HTTP 服务器使用时所固有它通常将为每个 Web 应用提供服务文件限制为该应用目录中那些文件但 servlet 应用可以避开这些限制当 Tomcat 和诸如 Apache 的类别前端 Web 服务器共同执行时也会发生这种情况

透过使用 chroot您可以阻止 Tomcat(和所有在 Tomcat 下执行 Web 应用)存取为该服务器留出空间以外任何东西chroot 并不以任何方式特定于 Java 应用但它是为 JVM 提供安全性加入最终包装器简便思路方法我将在这里为那些不熟悉 chroot 概念人介绍设定它要点

chroot 所做类别似于用于执行 Java 代码 JVM 沙箱但它适用于文件系统本身chroot 执行条指令并将您指定位置设定成有效根目录所执行指令(可以是执行其它指令(包括应用) shell 指令码)只能存取所指定有效根目录下文件系统部分文件系统其余部分对于该指令来说完全不存在

要对诸如 Tomcat 的类别应用使用 chroot需要将些基本系统应用和链接库(包括实际 Java JDK 安装)复制到新虚拟根目录下这可能会占用许多空间 ─ 也许从百兆字节到千兆字节或更多 ─ 这取决于您想尽多少努力来将这些应用和链接库减少到最小设定它最简单思路方法也最浪费空间︰祇要将整个 /bin、/lib、/usr/bin 和 /usr/lib 目录树以及 Java 安装复制到新根目录下使 root 使用者成为对所有文件拥有者和唯授权写入者如果想要让磁盘使用率保持到最小可以有选择地只复制 chroot 中需要指令(包括基本指令如 ls、rm、echo 和 cat 等以及实际 Java 安装)以及那些指令使用库(透过使用 ldd 可以找到那些库)

接下来您将需要建立些额外目录作为般系统缩减版本这包括 /dev以及设备 /dev/null 和 /dev/zero;/etc 以及 /etc/passwd 和 /etc/group 文件已编辑版本(只保留 root 和 tomcat 项)也许还有主机如果正在多处理器系统上执行您还需要在新根目录下挂装 /proc 系统 JVM 使用该系统来协调各个处理器

最后为了在设定了 chroot 后仍作为使用者 tomcat 执行也许需要建置个可以在虚拟根目录下执行 su 指令版本(许多分发版般版本不容许这样做)要这样做可以从 GNU 项目获取 sh-utils 来源码并根据该来源码直接建置 su然后将它复制到新根目录 /bin 目录中

完成了所有这些设定后可以尝试以 root 使用者身份执行(假设新根目录位于 /home/tomcat)︰

/usr/sbin/chroot /home/tomcat /bin/su tomcat

如果设定正确这应该让您在新根目录下作为 tomcat 执行而且您可以尝试使用您指令码来启动和停止 Tomcat.在证实了所有东西都工作的后最后步就是将清单 3 中 Tomcat 服务定义变更成使用 chroot 来代替 su将 su 指令移到 tcstart.sh 指令码和 tcstop.sh 指令码还需要确保只能由 root 使用者修改这些指令码

希望这篇概述解释很清楚这个过程并不适合胆小人﹗如果您选择走使用 chroot 这条路线但以前没有使用过 chroot那么您定要参考网上 chroot 参考数据的以获取详细信息但是这确实会给您 Java 服务器代码可能最好隔离而且在某些情况下带来内心宁静值得这样做

结语

Linux 和 Java 技术都正在赢得商业系统市场份额尽管开放来源码 Linux 和特许 Java 技术的间存在着原理上差异但这两者在起确实配合得很好Linux 对于 Java 应用尤其是对于服务器类别型应用个极好部署环境而 Java 技术是作为企业软件Software开发先进思路方法而建立且得到了认可

透过正确预防措施在 Linux 上执行 Java 服务器应用可以提供非常高安全性程度 ─ 甚至高于本机应用 Java 技术消除了服务器应用中许多弱点常见来源Java 技术跨平台性质所带来是包括企业工作人员和 Linux 立即就绪应用巨大资源集合Java 服务器应用开始在日益增长 Linux 服务器市场份额中扮演重要角色而且这种趋势在将来只会帮助这两种技术

我要感谢 Miles Sabin 向我指出了 /proc 文件系统来解决在多处理器系统上 chroot Java 问题



Tags:  javaforlinux linuxjava linuxjava环境 linuxjava环境变量

延伸阅读

最新评论

发表评论