0%

内网使用域名或公网IP访问同一个子网对外提供服务的服务器时,如不做特殊设置将无法访问,通过在内网接口上配置与公网接口相同的NAT设置可以解决此问题,实际上是对内网的源IP进行了NAT替换,替换成了防火墙内网接口的地址,从而使返回的数据包可以回流到防火墙再替换成正确的源IP,否则因为访问者和服务器在相同的内部网络中,数据包会走内部路由规则直接返回给访问者,由于数据包来源于内网ip而不是公网ip,会被访问者拒绝。但是ICMP不受此影响,如果用ping程序测试,网络看起来是通畅的。

也就是说,端口回流时,对数据包的源ip和目标ip都做了替换,源ip替换成了防火墙内网接口的ip,而目标ip替换成了内网真正提供服务机器的ip,相应包返回到防火墙内网接口时,根据此前的替换记录,将ip地址再对调回来就ok了。

1
2
3
4
$ telnet x.x.x.x
<fw> system-view
\[fw\] interface xxx
\[fw\] nat server ...

注意:还要在内网接口上做相应的acl规则以允许相应的内网流量从防火墙的内网接口通过。
比如内网接口的acl添加如下规则:

1
rule 211 permit ip source 192.168.2.0 0.0.0.255 destination 192.168.0.3 0 

以允许192.168.2.0/24网段的机器可以通过内网接口访问192.168.0.3这台机器。

或者

1
rule 216 permit ip destination 192.168.0.3 0

允许所有的机器可以通过内网接口访问192.168.0.3这台机器。

UPDATE(05/26/2016):
但这样设置会造成一个问题,所有的访问流量无论内外网都会被替换源地址,这可能不是你想要的。
参见H3C SecPath防火墙内部服务器NAT访问所有源地址被替换问题

对端口回流问题的详述见Reference[1]

H3C还有一种技术叫dns-map,其实这玩意儿的思路和Great Fucking Wall的DNS污染如出一辙,都是将DNS服务器返回的IP地址替换掉,不过一个是替换成错误的,而另一个是替换成更准确的(可以通过内网直接访问的)。

References:
[1]端口回流与dns-map与域内NAT
[2]华为防火墙域之间inbound和outbound之间的区别!
[3]用传统的NAT方式替代H3C的DNS-MAP功能
[4]outbound与inbound的区别——华为
[5]linux 做防火墙端口回流问题

===
[erq]

删除一个远程分支时出现错误提示:

1
$ git push --delete origin foobar

remote: error: By default, deleting the current branch is denied, because the next
remote: error: ‘git clone’ won’t result in any file checked out, causing confusion.
remote: error:
remote: error: You can set ‘receive.denyDeleteCurrent’ configuration variable to
remote: error: ‘warn’ or ‘ignore’ in the remote repository to allow deleting the
remote: error: current branch, with or without a warning message.
remote: error:
remote: error: To squelch this message, you can set it to ‘refuse’.
remote: error: refusing to delete the current branch: refs/heads/foobar
To cisvr:/reis.git
! [remote rejected] foobar (deletion of the current branch prohibited)
error: failed to push some refs to ‘cisvr:
/reis.git’

也就是foobar是远程仓库的当前分支(由于使用git clone --bare生成裸仓库造成的),因为远程仓库是裸仓库,所以不能使用普通的git checkout命令切换分支。在裸仓库中使用如下命令来切换当前分支:

1
$ git symbolic-ref HEAD refs/heads/devel

这样就将裸仓库的当前分支切换为devel分支,删除foobar分支就没问题了。

1
$ git push origin :foobar

这个命令实质上是修改了.git/HEAD文件,使其内容为:

1
ref: refs/heads/devel

===
[erq]

挂载NTFS分区一定要用ntfs-3g而不要用ntfs,传统的ntfs驱动读取还可以,不过也有问题,写会存在很多问题。 #linux#

替换元素

其内容不受CSS视觉格式化模型控制的元素,比如image,嵌入的文档(iframe之类)或者applet,叫做替换元素。比如,img元素的内容通常会被其src属性指定的图像替换掉。替换元素通常有其固有的尺寸:一个固有的宽度,一个固有的高度和一个固有的比率。比如一幅位图有固有用绝对单位指定的宽度和高度,从而也有固有的宽高比率。另一方面,其他文档也可能没有固有的尺寸,比如一个空白的html文档。

CSS渲染模型不考虑替换元素内容的渲染。这些替换元素的展现独立于CSS。object,video,textarea,input也是替换元素,audio和canvas在某些特定情形下为替换元素。使用CSS的content属性插入的对象是匿名替换元素。

固有尺寸

宽度和高度是有元素自身定义的,不受周围元素的影响。CSS没有定义如何去寻找替换元素的固有尺寸。在CSS 2.1中,只有替换元素可以有固有的尺寸。对于没有可靠的解析度信息的光栅图像,必须假定一个图像源像素为一个px单位。

一些CSS属性比如vertical-align可能会用到替换元素的固有尺寸或基线。

非替换元素

替换元素之外的所有其他元素都是非替换元素,由CSS的视觉格式化模型负责非替换元素的渲染。

混乱的术语

看到有些文章中将这两种元素称作可替换元素和不可替换元素,这种叫法很明显是错误的。
首先,从w3c标准的原始定义中替换元素使用了Replaced而不是Replaceable。
其次,替换元素和非替换元素是已经被替换(CSS不负责其展示渲染,由其固有属性接管渲染)和不会被替换(由CSS负责展示渲染),而不是可不可以被替换的概念。

References:
[1]Replaced element
[2]MDN:Replaced element

===
[erq]

window.print()函数会打印整个浏览器窗口的内容。如果只想打印页面的部分内容,可以在print css样式中隐藏不想打印的内容,但这样样式写起来会比较繁琐。可以将需要打印的内容放在一个div容器中,然后使用javascript生成一个新窗口,将div内容写入新窗口,最后打印整个新窗口就可以了,简单明了。

简单的样例代码:
[javascript]
$(‘#print_button’).click(function(){
var print_window = window.open(“print”,”_blank”);
var doc = print_window.document;
doc.write(‘‘);
doc.write(‘打印申请书‘);
doc.write(‘‘);
doc.write(‘‘);
doc.write(‘‘);
doc.write(‘‘);
doc.write($(‘#foodiv’).html());
doc.write(““);
doc.close();
print_window.print();
print_window.close();
});
[/javascript]

点击打印按钮就可以打印指定div的内容了,div的内容使用print css指定打印样式。

===
[erq]

显示器(screen)和打印机(printer)是两种差别很大的设备,所以从浏览器里看到的页面,打印出来也许和你看到的样子有很大的差距。screen一般使用逻辑单位比如px,而打印机则应该使用物理单位比如cm或in。我们常见的A4纸张大小在不同DPI的显示器上显示的大小是不同的。因此如果要精确的控制打印效果就应该使用print css,这是跨平台兼容的标准。不推荐使用浏览器插件方式实现打印。

web打印还有一种解决方式是生成pdf格式文件,客户端下载来打印,这也是不错的一种打印方式,因为pdf本身就是一种打印标准,可以做到精确控制。可以使用jsPDF在客户端动态生成pdf,也可以在服务器端使用一些组件生成pdf后传送给客户端。当然首选还是使用print css来实现打印。

引入print css

  • 使用link标签
    就像通常在html页面中引入样式表一样,不过附加一个额外的media属性,如下面这样:
    [html] \[/html\] 表明print.css样式表是用于打印的
  • 使用@media规则
    可以在通用的样式表中,使用@media规则指定样式用于打印,比如这样:
    [html]
    @media print selector {

    }
    [/html]
    或者
    [html]
    @media print {
    selector {

    }
    }
    [/html]
  • 使用@import规则
    使用@import规则在通用的样式表中导入打印样式表,有两种形式,其本质是一样的。
    css文件中:
    [html]
    @import url(print-style.css) print;
    [/html]

html文件中:
[html]

[/html]

使用link标签要比使用@import规则性能更好。

度量单位

显示时一般使用px,em或pt等逻辑单位,但在打印时要使用物理单位,比如cm或in(英寸)。对于常见的DPI(Dot Per Inch)为96的screen,px与cm的换算关系如下:

1 inch = 2.54 cm
1cm = 96/2.54 ≈ 37.80 px
1px = 2.54/96 ≈ 0.0265 cm
100px = 2.65 cm

A4纸的标准尺寸为:
21.0cm * 29.7 cm

在96DPI分辨率下,其对应的像素尺寸大约为:
794px * 1123px

因为不同的DPI下,其对应的像素尺寸是不同的,所以才要使用print css,使用物理单位来描述要打印的页面,这样打印效果就会一致了。

@page规则(at-rule)

@page 规则用于指定打印页面的一些属性,包括纸张尺寸,方向,页边距,分页等特性。其语法如下:

[html]
@page :pseudo-class {
size: A4 landscape;
margin:2cm;
}
[/html]
其中伪类可以指定:

  • :first
    指定第一页
  • :left
    指定左侧页面
  • :right
    指定右侧页面

分页(paginate)

有几个用于控制打印分页的属性可以用于常规的标签元素:

  • page-break-before
    用于设置元素前面的分页行为,可取值:

  • auto
    默认值。如果必要则在元素前插入分页符。

  • always
    在元素前插入分页符。

  • avoid
    避免在元素前插入分页符。

  • left
    在元素之前足够的分页符,一直到一张空白的左页为止。

  • right
    在元素之前足够的分页符,一直到一张空白的右页为止。

  • inherit
    规定应该从父元素继承 page-break-before 属性的设置。

  • page-break-after
    设置元素后的分页行为。取值与page-break-before一样。

  • page-break-inside
    设置元素内部的分页行为。取值如下:

  • auto
    默认。如果必要则在元素内部插入分页符。

  • avoid
    避免在元素内部插入分页符。

  • inherit
    规定应该从父元素继承 page-break-inside 属性的设置。

比如:
[html]
@media print {
section {page-break-before: always;}
h1 {page-break-after: always;}
p {page-break-inside: avoid;}
}
[/html]

  • orphans
    设置当元素内部发生分页时必须在页面底部保留的最少行数。
  • widows
    设置当元素内部发生分页时必须在页面顶部保留的最少行数。比如:
    [html]
    @media print {
    p {orphans:3; widows:2;}
    }
    [/html]

其他
对于页面上有显示而不想打印的内容,可以将其display设置为none来避免打印。需要打印的内容尽量避免float,有些浏览器不会正确的打印浮动的内容。

可以调用window.print()函数来打印当前页面。

References:
[1]CSS for print tutorial
[2]@page
[3]CSS 打印属性(Print)

===
[erq]

这几天写CSS的时候发现一个奇怪的现象,子元素的margin-top会影响父元素的margin-top。本来父元素只是一个简单的容器,没有设置样式,第一个子元素设置了margin-top后,父元素也具有了一样的margin-top,原来是边距合并(Margin Collapse)在作怪。

普通文档流中相邻的块框,还有父元素与第一个子元素的上边距,父元素与最后一个子元素的下边距都有可能会发生外边距合并,这其中有些复杂的规则存在,与BFC(Block formatting contexts)密切相关,在同一个BFC(块格式化上下文)中,相邻的块级框之间的垂直外边距会出现折叠。详细的描述见参考文档[1]和[2],文档[1]描述的十分详细,这里就没必要再重复了。

防止父子元素外边据合并的常用方法有:

  • 父元素设置overflow:visible之外的其他值
  • 父元素设置border
    比如设置一个1px透明的border
    [css]
    border: 1px solid transparent;/透明边框,防止父子元素垂直边距合并/
    [/css]
  • 父元素或子元素设置float属性
  • 父元素设置padding-top(padding-top:1px)
  • 设置父元素或者自身display:inline-block
  • 父元素或子元素绝对定位(absolute或fix)
  • 设置父元素非空,填充一定的内容

注意:只有普通文档流中块框的垂直外边距才会发生外边距合并。行内框、浮动框或绝对定位之间的外边距不会合并。

References:
[1]深入理解BFC和Margin Collapse
[2]CSS 外边距合并
[3]由浅入深漫谈margin属性

===
[erq]

规范的编写网页的方法是在最合适的地方用最合语义的代码/标签构建网页HTML结构骨架,以CSS形式定制其外观样式,以Javascript描述其行为动作。