yannstatic/static/2021/04/17/OpenWrt-Creation-routeur-4G-Raspberry-Pi-telephone-portable(NEW).html

2480 lines
215 KiB
HTML
Raw Permalink Normal View History

2024-10-31 20:18:37 +01:00
<!DOCTYPE html><html lang="fr">
<head><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"><title>OpenWrt - Création d'un routeur 4G à l'aide d'un Raspberry Pi - YannStatic</title>
<meta name="description" content="OpenWrt sur Raspberry Pi">
<link rel="canonical" href="https://static.rnmkcy.eu/2021/04/17/OpenWrt-Creation-routeur-4G-Raspberry-Pi-telephone-portable(NEW).html"><link rel="alternate" type="application/rss+xml" title="YannStatic" href="/feed.xml">
<!-- - include head/favicon.html - -->
<link rel="shortcut icon" type="image/png" href="/assets/favicon/favicon.png"><link rel="stylesheet" href="/assets/css/main.css"><link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" ><!-- start custom head snippets --><link rel="stylesheet" href="/assets/css/expand.css">
<!-- end custom head snippets --><script>(function() {
window.isArray = function(val) {
return Object.prototype.toString.call(val) === '[object Array]';
};
window.isString = function(val) {
return typeof val === 'string';
};
window.hasEvent = function(event) {
return 'on'.concat(event) in window.document;
};
window.isOverallScroller = function(node) {
return node === document.documentElement || node === document.body || node === window;
};
window.isFormElement = function(node) {
var tagName = node.tagName;
return tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA';
};
window.pageLoad = (function () {
var loaded = false, cbs = [];
window.addEventListener('load', function () {
var i;
loaded = true;
if (cbs.length > 0) {
for (i = 0; i < cbs.length; i++) {
cbs[i]();
}
}
});
return {
then: function(cb) {
cb && (loaded ? cb() : (cbs.push(cb)));
}
};
})();
})();
(function() {
window.throttle = function(func, wait) {
var args, result, thisArg, timeoutId, lastCalled = 0;
function trailingCall() {
lastCalled = new Date;
timeoutId = null;
result = func.apply(thisArg, args);
}
return function() {
var now = new Date,
remaining = wait - (now - lastCalled);
args = arguments;
thisArg = this;
if (remaining <= 0) {
clearTimeout(timeoutId);
timeoutId = null;
lastCalled = now;
result = func.apply(thisArg, args);
} else if (!timeoutId) {
timeoutId = setTimeout(trailingCall, remaining);
}
return result;
};
};
})();
(function() {
var Set = (function() {
var add = function(item) {
var i, data = this._data;
for (i = 0; i < data.length; i++) {
if (data[i] === item) {
return;
}
}
this.size ++;
data.push(item);
return data;
};
var Set = function(data) {
this.size = 0;
this._data = [];
var i;
if (data.length > 0) {
for (i = 0; i < data.length; i++) {
add.call(this, data[i]);
}
}
};
Set.prototype.add = add;
Set.prototype.get = function(index) { return this._data[index]; };
Set.prototype.has = function(item) {
var i, data = this._data;
for (i = 0; i < data.length; i++) {
if (this.get(i) === item) {
return true;
}
}
return false;
};
Set.prototype.is = function(map) {
if (map._data.length !== this._data.length) { return false; }
var i, j, flag, tData = this._data, mData = map._data;
for (i = 0; i < tData.length; i++) {
for (flag = false, j = 0; j < mData.length; j++) {
if (tData[i] === mData[j]) {
flag = true;
break;
}
}
if (!flag) { return false; }
}
return true;
};
Set.prototype.values = function() {
return this._data;
};
return Set;
})();
window.Lazyload = (function(doc) {
var queue = {js: [], css: []}, sources = {js: {}, css: {}}, context = this;
var createNode = function(name, attrs) {
var node = doc.createElement(name), attr;
for (attr in attrs) {
if (attrs.hasOwnProperty(attr)) {
node.setAttribute(attr, attrs[attr]);
}
}
return node;
};
var end = function(type, url) {
var s, q, qi, cbs, i, j, cur, val, flag;
if (type === 'js' || type ==='css') {
s = sources[type], q = queue[type];
s[url] = true;
for (i = 0; i < q.length; i++) {
cur = q[i];
if (cur.urls.has(url)) {
qi = cur, val = qi.urls.values();
qi && (cbs = qi.callbacks);
for (flag = true, j = 0; j < val.length; j++) {
cur = val[j];
if (!s[cur]) {
flag = false;
}
}
if (flag && cbs && cbs.length > 0) {
for (j = 0; j < cbs.length; j++) {
cbs[j].call(context);
}
qi.load = true;
}
}
}
}
};
var load = function(type, urls, callback) {
var s, q, qi, node, i, cur,
_urls = typeof urls === 'string' ? new Set([urls]) : new Set(urls), val, url;
if (type === 'js' || type ==='css') {
s = sources[type], q = queue[type];
for (i = 0; i < q.length; i++) {
cur = q[i];
if (_urls.is(cur.urls)) {
qi = cur;
break;
}
}
val = _urls.values();
if (qi) {
callback && (qi.load || qi.callbacks.push(callback));
callback && (qi.load && callback());
} else {
q.push({
urls: _urls,
callbacks: callback ? [callback] : [],
load: false
});
for (i = 0; i < val.length; i++) {
node = null, url = val[i];
if (s[url] === undefined) {
(type === 'js' ) && (node = createNode('script', { src: url }));
(type === 'css') && (node = createNode('link', { rel: 'stylesheet', href: url }));
if (node) {
node.onload = (function(type, url) {
return function() {
end(type, url);
};
})(type, url);
(doc.head || doc.body).appendChild(node);
s[url] = false;
}
}
}
}
}
};
return {
js: function(url, callback) {
load('js', url, callback);
},
css: function(url, callback) {
load('css', url, callback);
}
};
})(this.document);
})();
</script><script>
(function() {
var TEXT_VARIABLES = {
version: '2.2.6',
sources: {
font_awesome: 'https://use.fontawesome.com/releases/v5.0.13/css/all.css',
jquery: '/assets/js/jquery.min.js',
leancloud_js_sdk: '//cdn.jsdelivr.net/npm/leancloud-storage@3.13.2/dist/av-min.js',
chart: 'https://cdn.bootcss.com/Chart.js/2.7.2/Chart.bundle.min.js',
gitalk: {
js: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.js',
css: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.css'
},
valine: 'https://unpkg.com/valine/dist/Valine.min.js'
},
site: {
toc: {
selectors: 'h1,h2,h3'
}
},
paths: {
search_js: '/assets/search.js'
}
};
window.TEXT_VARIABLES = TEXT_VARIABLES;
})();
</script>
</head>
<body>
<div class="root" data-is-touch="false">
<div class="layout--page js-page-root"><!----><div class="page__main js-page-main page__viewport hide-footer has-aside has-aside cell cell--auto">
<div class="page__main-inner"><div class="page__header d-print-none"><header class="header"><div class="main">
<div class="header__title">
<div class="header__brand"><svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="478.9473684210526" viewBox="0, 0, 400,478.9473684210526"><g id="svgg"><path id="path0" d="M308.400 56.805 C 306.970 56.966,303.280 57.385,300.200 57.738 C 290.906 58.803,278.299 59.676,269.200 59.887 L 260.600 60.085 259.400 61.171 C 258.010 62.428,256.198 63.600,255.645 63.600 C 255.070 63.600,252.887 65.897,252.598 66.806 C 252.460 67.243,252.206 67.600,252.034 67.600 C 251.397 67.600,247.206 71.509,247.202 72.107 C 247.201 72.275,246.390 73.190,245.400 74.138 C 243.961 75.517,243.598 76.137,243.592 77.231 C 243.579 79.293,241.785 83.966,240.470 85.364 C 239.176 86.740,238.522 88.365,237.991 91.521 C 237.631 93.665,236.114 97.200,235.554 97.200 C 234.938 97.200,232.737 102.354,232.450 104.472 C 232.158 106.625,230.879 109.226,229.535 110.400 C 228.933 110.926,228.171 113.162,226.434 119.500 C 226.178 120.435,225.795 121.200,225.584 121.200 C 225.373 121.200,225.200 121.476,225.200 121.813 C 225.200 122.149,224.885 122.541,224.500 122.683 C 223.606 123.013,223.214 123.593,223.204 124.600 C 223.183 126.555,220.763 132.911,219.410 134.562 C 218.443 135.742,217.876 136.956,217.599 138.440 C 217.041 141.424,215.177 146.434,214.532 146.681 C 214.240 146.794,214.000 147.055,214.000 147.261 C 214.000 147.467,213.550 148.086,213.000 148.636 C 212.450 149.186,212.000 149.893,212.000 150.208 C 212.000 151.386,208.441 154.450,207.597 153.998 C 206.319 153.315,204.913 150.379,204.633 147.811 C 204.365 145.357,202.848 142.147,201.759 141.729 C 200.967 141.425,199.200 137.451,199.200 135.974 C 199.200 134.629,198.435 133.224,196.660 131.311 C 195.363 129.913,194.572 128.123,193.870 125.000 C 193.623 123.900,193.236 122.793,193.010 122.540 C 190.863 120.133,190.147 118.880,188.978 115.481 C 188.100 112.928,187.151 111.003,186.254 109.955 C 185.358 108.908,184.518 107.204,183.847 105.073 C 183.280 103.273,182.497 101.329,182.108 100.753 C 181.719 100.177,180.904 98.997,180.298 98.131 C 179.693 97.265,178.939 95.576,178.624 94.378 C 178.041 92.159,177.125 90.326,175.023 87.168 C 174.375 86.196,173.619 84.539,173.342 83.486 C 172.800 81.429,171.529 79.567,170.131 78.785 C 169.654 78.517,168.697 77.511,168.006 76.549 C 167.316 75.587,166.594 74.800,166.402 74.800 C 166.210 74.800,164.869 73.633,163.421 72.206 C 160.103 68.936,161.107 69.109,146.550 69.301 C 133.437 69.474,128.581 70.162,126.618 72.124 C 126.248 72.495,125.462 72.904,124.872 73.033 C 124.282 73.163,123.088 73.536,122.219 73.863 C 121.349 74.191,119.028 74.638,117.061 74.858 C 113.514 75.254,109.970 76.350,108.782 77.419 C 107.652 78.436,100.146 80.400,97.388 80.400 C 95.775 80.400,93.167 81.360,91.200 82.679 C 90.430 83.195,89.113 83.804,88.274 84.031 C 85.875 84.681,78.799 90.910,74.400 96.243 L 73.400 97.456 73.455 106.028 C 73.526 117.055,74.527 121.238,77.820 124.263 C 78.919 125.273,80.400 127.902,80.400 128.842 C 80.400 129.202,81.075 130.256,81.900 131.186 C 83.563 133.059,85.497 136.346,86.039 138.216 C 86.233 138.886,87.203 140.207,88.196 141.153 C 89.188 142.098,90.000 143.104,90.000 143.388 C 90.000 144.337,92.129 148.594,92.869 149.123 C 93.271 149.410,93.600 149.831,93.600 150.059 C 93.600 150.286,93.932 150.771,94.337 151.136 C 94.743 151.501,95.598 153.004,96.237 154.475 C 96.877 155.947,97.760 157.351,98.200 157.596 C 98.640 157.841,99.900 159.943,101.000 162.267 C 102.207 164.817,103.327 166.644,103.825 166.876 C 104.278 167.087,105.065 168.101,105.573 169.130 C 107.658 173.348,108.097 174.093,110.006 176.647 C 111.103 178.114,112.000 179.725,112.000 180.227 C 112.000 181.048,113.425 183.163,114.678 184.200 C 115.295 184.711,117.396 188.733,117.720 190.022 C 117.855 190.562,118.603 191.633,119.381 192.402 C 120.160 193.171,121.496 195.258,122.351 197.039 C 123.206 198.820,124.167 200.378,124.487 200.501 C 124.807 200.624,125.953 202.496,127.034 204.662 C 128.114 206.828,129.676 209.299,130.505 210.153 C 131.333 211.007,132.124 212.177,132.262 212.753 C 132.618 214.239,134.291 217.048,136.288 219.5
" href="/">YannStatic</a></div><!--<button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button>--><!-- <li><button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button></li> -->
<!-- Champ de recherche -->
<div id="searchbox" class="search search--dark" style="visibility: visible">
<div class="main">
<div class="search__header"></div>
<div class="search-bar">
<div class="search-box js-search-box">
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
<input id="search-input" type="text" />
<!-- <div class="search-box__icon-clear js-icon-clear">
<a><i class="fas fa-times"></i></a>
</div> -->
</div>
</div>
</div>
</div>
<!-- Script pointing to search-script.js -->
<script>/*!
* Simple-Jekyll-Search
* Copyright 2015-2020, Christian Fei
* Licensed under the MIT License.
*/
(function(){
'use strict'
var _$Templater_7 = {
compile: compile,
setOptions: setOptions
}
const options = {}
options.pattern = /\{(.*?)\}/g
options.template = ''
options.middleware = function () {}
function setOptions (_options) {
options.pattern = _options.pattern || options.pattern
options.template = _options.template || options.template
if (typeof _options.middleware === 'function') {
options.middleware = _options.middleware
}
}
function compile (data) {
return options.template.replace(options.pattern, function (match, prop) {
const value = options.middleware(prop, data[prop], options.template)
if (typeof value !== 'undefined') {
return value
}
return data[prop] || match
})
}
'use strict';
function fuzzysearch (needle, haystack) {
var tlen = haystack.length;
var qlen = needle.length;
if (qlen > tlen) {
return false;
}
if (qlen === tlen) {
return needle === haystack;
}
outer: for (var i = 0, j = 0; i < qlen; i++) {
var nch = needle.charCodeAt(i);
while (j < tlen) {
if (haystack.charCodeAt(j++) === nch) {
continue outer;
}
}
return false;
}
return true;
}
var _$fuzzysearch_1 = fuzzysearch;
'use strict'
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
function FuzzySearchStrategy () {
this.matches = function (string, crit) {
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
}
}
'use strict'
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
function LiteralSearchStrategy () {
this.matches = function (str, crit) {
if (!str) return false
str = str.trim().toLowerCase()
crit = crit.trim().toLowerCase()
return crit.split(' ').filter(function (word) {
return str.indexOf(word) >= 0
}).length === crit.split(' ').length
}
}
'use strict'
var _$Repository_4 = {
put: put,
clear: clear,
search: search,
setOptions: __setOptions_4
}
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
function NoSort () {
return 0
}
const data = []
let opt = {}
opt.fuzzy = false
opt.limit = 10
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = NoSort
opt.exclude = []
function put (data) {
if (isObject(data)) {
return addObject(data)
}
if (isArray(data)) {
return addArray(data)
}
return undefined
}
function clear () {
data.length = 0
return data
}
function isObject (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
}
function isArray (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
}
function addObject (_data) {
data.push(_data)
return data
}
function addArray (_data) {
const added = []
clear()
for (let i = 0, len = _data.length; i < len; i++) {
if (isObject(_data[i])) {
added.push(addObject(_data[i]))
}
}
return added
}
function search (crit) {
if (!crit) {
return []
}
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
}
function __setOptions_4 (_opt) {
opt = _opt || {}
opt.fuzzy = _opt.fuzzy || false
opt.limit = _opt.limit || 10
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = _opt.sort || NoSort
opt.exclude = _opt.exclude || []
}
function findMatches (data, crit, strategy, opt) {
const matches = []
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
const match = findMatchesInObject(data[i], crit, strategy, opt)
if (match) {
matches.push(match)
}
}
return matches
}
function findMatchesInObject (obj, crit, strategy, opt) {
for (const key in obj) {
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
return obj
}
}
}
function isExcluded (term, excludedTerms) {
for (let i = 0, len = excludedTerms.length; i < len; i++) {
const excludedTerm = excludedTerms[i]
if (new RegExp(excludedTerm).test(term)) {
return true
}
}
return false
}
/* globals ActiveXObject:false */
'use strict'
var _$JSONLoader_2 = {
load: load
}
function load (location, callback) {
const xhr = getXHR()
xhr.open('GET', location, true)
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
xhr.send()
}
function createStateChangeListener (xhr, callback) {
return function () {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
callback(null, JSON.parse(xhr.responseText))
} catch (err) {
callback(err, null)
}
}
}
}
function getXHR () {
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
}
'use strict'
var _$OptionsValidator_3 = function OptionsValidator (params) {
if (!validateParams(params)) {
throw new Error('-- OptionsValidator: required options missing')
}
if (!(this instanceof OptionsValidator)) {
return new OptionsValidator(params)
}
const requiredOptions = params.required
this.getRequiredOptions = function () {
return requiredOptions
}
this.validate = function (parameters) {
const errors = []
requiredOptions.forEach(function (requiredOptionName) {
if (typeof parameters[requiredOptionName] === 'undefined') {
errors.push(requiredOptionName)
}
})
return errors
}
function validateParams (params) {
if (!params) {
return false
}
return typeof params.required !== 'undefined' && params.required instanceof Array
}
}
'use strict'
var _$utils_9 = {
merge: merge,
isJSON: isJSON
}
function merge (defaultParams, mergeParams) {
const mergedOptions = {}
for (const option in defaultParams) {
mergedOptions[option] = defaultParams[option]
if (typeof mergeParams[option] !== 'undefined') {
mergedOptions[option] = mergeParams[option]
}
}
return mergedOptions
}
function isJSON (json) {
try {
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
return true
}
return false
} catch (err) {
return false
}
}
var _$src_8 = {};
(function (window) {
'use strict'
let options = {
searchInput: null,
resultsContainer: null,
json: [],
success: Function.prototype,
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
templateMiddleware: Function.prototype,
sortMiddleware: function () {
return 0
},
noResultsText: 'No results found',
limit: 10,
fuzzy: false,
debounceTime: null,
exclude: []
}
let debounceTimerHandle
const debounce = function (func, delayMillis) {
if (delayMillis) {
clearTimeout(debounceTimerHandle)
debounceTimerHandle = setTimeout(func, delayMillis)
} else {
func.call()
}
}
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
/* removed: const _$Templater_7 = require('./Templater') */;
/* removed: const _$Repository_4 = require('./Repository') */;
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
const optionsValidator = _$OptionsValidator_3({
required: requiredOptions
})
/* removed: const _$utils_9 = require('./utils') */;
window.SimpleJekyllSearch = function (_options) {
const errors = optionsValidator.validate(_options)
if (errors.length > 0) {
throwError('You must specify the following required options: ' + requiredOptions)
}
options = _$utils_9.merge(options, _options)
_$Templater_7.setOptions({
template: options.searchResultTemplate,
middleware: options.templateMiddleware
})
_$Repository_4.setOptions({
fuzzy: options.fuzzy,
limit: options.limit,
sort: options.sortMiddleware,
exclude: options.exclude
})
if (_$utils_9.isJSON(options.json)) {
initWithJSON(options.json)
} else {
initWithURL(options.json)
}
const rv = {
search: search
}
typeof options.success === 'function' && options.success.call(rv)
return rv
}
function initWithJSON (json) {
_$Repository_4.put(json)
registerInput()
}
function initWithURL (url) {
_$JSONLoader_2.load(url, function (err, json) {
if (err) {
throwError('failed to get JSON (' + url + ')')
}
initWithJSON(json)
})
}
function emptyResultsContainer () {
options.resultsContainer.innerHTML = ''
}
function appendToResultsContainer (text) {
options.resultsContainer.innerHTML += text
}
function registerInput () {
options.searchInput.addEventListener('input', function (e) {
if (isWhitelistedKey(e.which)) {
emptyResultsContainer()
debounce(function () { search(e.target.value) }, options.debounceTime)
}
})
}
function search (query) {
if (isValidQuery(query)) {
emptyResultsContainer()
render(_$Repository_4.search(query), query)
}
}
function render (results, query) {
const len = results.length
if (len === 0) {
return appendToResultsContainer(options.noResultsText)
}
for (let i = 0; i < len; i++) {
results[i].query = query
appendToResultsContainer(_$Templater_7.compile(results[i]))
}
}
function isValidQuery (query) {
return query && query.length > 0
}
function isWhitelistedKey (key) {
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
}
function throwError (message) {
throw new Error('SimpleJekyllSearch --- ' + message)
}
})(window)
}());
</script>
<!-- Configuration -->
<script>
SimpleJekyllSearch({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
json: '/search.json',
//searchResultTemplate: '<li><a href="https://static.rnmkcy.eu{url}">{date}&nbsp;{title}</a></li>'
searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{title}</a></li>'
})
</script>
<!-- Fin déclaration champ de recherche --></div><nav class="navigation">
<ul><li class="navigation__item"><a href="/archive.html">Etiquettes</a></li><li class="navigation__item"><a href="/htmldoc.html">Documents</a></li><li class="navigation__item"><a href="/liens_ttrss.html">Liens</a></li><li class="navigation__item"><a href="/aide-jekyll-text-theme.html">Aide</a></li></ul>
</nav></div>
</header>
</div><div class="page__content"><div class ="main"><div class="grid grid--reverse">
<div class="col-main cell cell--auto"><!-- start custom main top snippet --><div id="results-container" class="search-result js-search-result"></div><!-- end custom main top snippet -->
<article itemscope itemtype="http://schema.org/Article"><div class="article__header"><header><h1 style="color:Tomato;">OpenWrt - Création d'un routeur 4G à l'aide d'un Raspberry Pi</h1></header></div><meta itemprop="headline" content="OpenWrt - Création d'un routeur 4G à l'aide d'un Raspberry Pi"><div class="article__info clearfix"><ul class="left-col menu"><li>
2024-11-08 14:10:33 +01:00
<a class="button button--secondary button--pill button--sm" style="color:#00FFFF" href="/archive.html?tag=openwrt">openwrt</a>
2024-10-31 20:18:37 +01:00
</li></ul><ul class="right-col menu"><li>
<i class="far fa-calendar-alt"></i>&nbsp;<span title="Création" style="color:#FF00FF">17&nbsp;avr.&nbsp;&nbsp;2021</span>
<span title="Modification" style="color:#00FF7F">27&nbsp;nov.&nbsp;&nbsp;2021</span></li></ul></div><meta itemprop="datePublished" content="2021-11-27T00:00:00+01:00">
<meta itemprop="keywords" content="openwrt"><div class="js-article-content">
<div class="layout--article"><!-- start custom article top snippet -->
<style>
#myBtn {
display: none;
position: fixed;
bottom: 10px;
right: 10px;
z-index: 99;
font-size: 12px;
font-weight: bold;
border: none;
outline: none;
background-color: white;
color: black;
cursor: pointer;
padding: 5px;
border-radius: 4px;
}
#myBtn:hover {
background-color: #555;
}
</style>
<button onclick="topFunction()" id="myBtn" title="Haut de page">&#8679;</button>
<script>
//Get the button
var mybutton = document.getElementById("myBtn");
// When the user scrolls down 20px from the top of the document, show the button
window.onscroll = function() {scrollFunction()};
function scrollFunction() {
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
mybutton.style.display = "block";
} else {
mybutton.style.display = "none";
}
}
// When the user clicks on the button, scroll to the top of the document
function topFunction() {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
}
</script>
<!-- end custom article top snippet -->
<div class="article__content" itemprop="articleBody"><details>
<summary><b>Afficher/cacher Sommaire</b></summary>
<!-- affichage sommaire -->
<div class="toc-aside js-toc-root"></div>
</details><h2 id="openwrt-sur-raspberry-pi">OpenWrt sur Raspberry Pi</h2>
<p><img src="/images/openwrt.png" alt="openwrt" width="200" /><br />
<img src="/images/openwrt20.png" alt="openwrt" width="600" /><br />
<em>Mettre en place dOpenWRT sur un Raspberry Pi pour réaliser une box 4G</em></p>
<h3 id="flash-sdcard-avec-image-rpi-openwrt">Flash SDcard avec image RPI OpenWRT</h3>
<p>Télécharger une image d<a href="https://openwrt.org/toh/raspberry_pi_foundation/raspberry_pi">OpenWRT compatible avec votre version de Raspberry Pi</a> (1, 2, 3, 4, Zero)</p>
<p><img src="/images/openwrt41.png" alt="openwrt" width="600" /></p>
<p><strong>Raspberry PI B+ : https://downloads.openwrt.org/releases/21.02.1/targets/bcm27xx/bcm2708/openwrt-21.02.1-bcm27xx-bcm2708-rpi-ext4-factory.img.gz</strong></p>
<p>Insérer une sdcard dans le lecteur USB/SDcard et en mode su <code class="language-plaintext highlighter-rouge">dmesg</code> pour visualiser les messages du kernel et ainsi connaitre le nom de périphérique de la carte SD (/dev/sdb ou /dev/sdf…etc)<br />
La carte SD est sur <code class="language-plaintext highlighter-rouge">/dev/sdc</code> (dans mon cas)<br />
Flasher la SDcard</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo dd if=openwrt-21.02.1-bcm27xx-bcm2708-rpi-ext4-factory.img of=/dev/sdd bs=2M conv=fsync
</code></pre></div></div>
<h3 id="openwrtraspberry-pi-b">OpenWrt/Raspberry PI B+</h3>
<p class="info">Insérer la SDcard dans le Raspberry Pi raccordé au réseau et le dongle Wifi USB Ralink RT5370<br />
On va utiliser un adaptateur USB/Serial et lapplication minicom pour se connecter via le port série en utilisant le connecteur GPIO (Pin 6 = Ground, Pin 8 = TX, Pin 10 = RX).</p>
<p>Il faut paramétrer le routeur OpenWRT pour un accès au réseau existant afin de mettre à jour et installer les applications</p>
<ul>
<li>Le routeur freebox est à ladresse 192.168.0.1</li>
<li>OpenWRT esr par défaut à ladresse 192.168.1.1</li>
</ul>
<p>On se met en écoute sur la liaison</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo minicom
# OUsu
sudo screen /dev/ttyUSB0 115200
</code></pre></div></div>
<p>Mettre sous tension le rasberry</p>
<p><img src="/images/openwrt04.png" alt="openwrt" width="400" /><br />
Créer le mot de passe root (Par défaut, le mot de passe est vide.) : <code class="language-plaintext highlighter-rouge">passwd</code></p>
<p><strong>Modifier ladresse IP : 192.168.1.1 → 192.168.0.1</strong><br />
<img src="/images/openwrt05.png" alt="openwrt" width="400" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vi /etc/config/network
</code></pre></div></div>
<p>Appuyez sur la touche “i” de votre clavier pour activer le mode édition, puis modifiez ladresse IP comme vous le souhaitez. 192.168.1.1 → 192.168.0.1</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>config interface 'loopback'
option ifname 'lo'
option proto 'static'
option ipaddr '127.0.0.1'
option netmask '255.0.0.0'
config globals 'globals'
option ula_prefix 'fdc4:62ff:57c6::/48'
config interface 'lan'
option type 'bridge'
option ifname 'eth0'
option proto 'static'
option ipaddr '192.168.0.1'
option netmask '255.255.255.0'
option ip6assign '60'
</code></pre></div></div>
<p>Appuyez sur la touche “Esc”, tapez :wq (w signifie écrire, q signifie quitter), puis appuyez sur ENTER pour appliquer. <br />
tapez <code class="language-plaintext highlighter-rouge">reboot</code> pour redémarrer votre routeur, puis vous pourrez vous connecter à votre routeur avec la nouvelle adresse IP en ssh : <code class="language-plaintext highlighter-rouge">ssh root@192.168.0.1</code></p>
<p>Vérification</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ip a
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc fq_codel master br-la0
link/ether b8:27:eb:66:0e:13 brd ff:ff:ff:ff:ff:ff
3: br-lan: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc noqueue state UP ql0
link/ether b8:27:eb:66:0e:13 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.1/24 brd 192.168.0.255 scope global br-lan
valid_lft forever preferred_lft forever
inet6 fdec:830e:614e::1/60 scope global noprefixroute
valid_lft forever preferred_lft forever
inet6 fe80::ba27:ebff:fe66:e13/64 scope link
valid_lft forever preferred_lft forever
</code></pre></div></div>
<p>**Ouvrez ensuite un navigateur et accédez à lIP du Routeur (http://192.168.0.1).</p>
<p class="warning">ATTENTION À UTILISER HTTP ET NON HTTPS</p>
<p>Se connecter “root” au WebUI<br />
<img src="/images/openwrt07.png" alt="openwrt" width="600" /><br />
Allez sur <strong>Network → Interfaces</strong><br />
<img src="/images/openwrt07-a.png" alt="openwrt" width="600" /><br />
Cliquez sur <strong>Edit</strong> et ajoutez un gateway 192.168.0.254 pour les mises à jour applications<br />
<img src="/images/openwrt08.png" alt="openwrt" width="600" /><br />
<img src="/images/openwrt08-a.png" alt="openwrt" width="600" /><br />
Cliquez sur <strong>Save</strong> puis <strong>Save &amp; Apply</strong></p>
<h3 id="agrandir-la-taille-du-disque">Agrandir la taille du disque</h3>
<p>La taille actuelle est restreinte</p>
<p><img src="/images/openwrt40.png" alt="" /></p>
<p><a href="https://samhobbs.co.uk/2013/11/more-space-for-packages-with-extroot-on-your-openwrt-router">Plus despace pour les paquets avec extroot sur votre routeur OpenWrt</a></p>
<p>Les <a href="http://wiki.openwrt.org/doc/howto/extroot">pages du wiki OpenWrt</a> sur ce sujet sont très bonnes. Si vous souhaitez en savoir plus sur les différentes options, jetez-y un coup doeil (par exemple, il est possible de monter le disque USB sur /opt et dinstaller des extras ici, mais certains paquets sattendent à être installés en root et ne se comporteront pas correctement).</p>
<p>Au cas où vous voudriez le vérifier plus tard, le type dextroot dont je parle ici est le root externe (alias pivot root), et non le overlay externe (alias pivot-overlay).</p>
<p><strong>Traitement</strong></p>
<p>Cela suppose que vous avez déjà formaté votre disque USB externe avec un système de fichiers de journalisation (comme EXT3 ou EXT4). Si ce nest pas le cas, faites-le dabord (les gestionnaires de partition dUbuntu et de Kubuntu le font très facilement, faites une recherche google pour un tutoriel si vous nêtes pas sûr de savoir comment le faire).</p>
<p>Pour utiliser la racine pivot, vous devez utiliser une version dOpenWrt qui est plus récente que la v12 (donc 12.09 Attitude Adjustment est bien, mais Backfire ne lest pas).</p>
<p>Tout dabord, connectez-vous à OpenWrt via ssh ou telnet.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>BusyBox v1.30.1 () built-in shell (ash)
_______ ________ __
| |.-----.-----.-----.| | | |.----.| |_
| - || _ | -__| || | | || _|| _|
|_______|| __|_____|__|__||________||__| |____|
|__| W I R E L E S S F R E E D O M
-----------------------------------------------------
OpenWrt 19.07.7, r11306-c4a6851c72
-----------------------------------------------------
</code></pre></div></div>
<p><strong>Installez les paquets</strong></p>
<p>Tout dabord, installez le paquet qui fera passer votre racine de la mémoire flash intégrée du routeur au périphérique flash USB externe :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opkg update
opkg install block-mount
</code></pre></div></div>
<p><strong>Copiez votre système de fichiers racine actuel sur la clé USB.</strong></p>
<p>Avant de faire cela, assurez-vous que votre routeur est sécurisé (par exemple, la connexion SSH nest pas possible depuis le WAN, les interfaces wifi sont protégées par un mot de passe, etc).</p>
<blockquote>
<p>Ceci est important car si quelque chose ne va pas au démarrage de votre routeur, OpenWrt sera incapable de démarrer sur la clé USB, vous laissant avec votre configuration actuelle jusquà ce que vous puissiez le faire démarrer correctement sur la clé USB.</p>
</blockquote>
<p>Tout dabord, installez fdisk, un outil qui vous donne des informations sur les périphériques attachés :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opkg update
opkg install fdisk
</code></pre></div></div>
<p>Maintenant, insérez votre clé USB et exécutez la commande suivante pour obtenir quelques détails sur elle :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>fdisk -l
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[...]
Disk /dev/sda: 14.33 GiB, 15376318464 bytes, 30031872 sectors
Disk model: SanDisk 3.2Gen1
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000
Device Boot Start End Sectors Size Id Type
/dev/sda1 2048 30031871 30029824 14.3G 83 Linux
</code></pre></div></div>
<p>Vous voyez votre lecteur USB listé sous “Device”. Maintenant, créez un point de montage pour le disque. Vous pouvez choisir ce que vous voulez à la place de sda1, rappelez-vous simplement ce que vous avez choisi plus tard !</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir /mnt/sda1
</code></pre></div></div>
<p>Montez le disque sur le point de montage que vous venez de créer</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mount /dev/sda1 /mnt/sda1
</code></pre></div></div>
<p>Maintenant, copiez le système de fichiers racine de la mémoire flash intégrée du routeur vers la clé USB avec ces commandes (si vous avez choisi un nom autre que /mnt/sda1 à létape précédente, remplacez /mnt/sda1 à la ligne 3) :</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir</span> <span class="nt">-p</span> /tmp/cproot
mount <span class="nt">--bind</span> / /tmp/cproot
<span class="nb">tar</span> <span class="nt">-C</span> /tmp/cproot <span class="nt">-cvf</span> - <span class="nb">.</span> | <span class="nb">tar</span> <span class="nt">-C</span> /mnt/sda1 <span class="nt">-xf</span> -
umount /tmp/cproot
</code></pre></div></div>
<p>Vous avez maintenant une clé USB avec une copie du système de fichiers de votre routeur. Létape suivante consiste à faire en sorte quelle se monte automatiquement au démarrage, et à lutiliser en tant que root.</p>
<p><strong>Configuration de /etc/config/fstab</strong></p>
<p>Si nano nest pas installé, vous pouvez utiliser vi (qui est installé par défaut) ou vous pouvez simplement installer nano avec :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opkg update &amp;&amp; opkg install nano
</code></pre></div></div>
<p>Ouvrez /etc/config/fstab avec votre éditeur de texte préféré :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/config/fstab
</code></pre></div></div>
<p>Ajoutez ce qui suit au fichier :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>config 'mount'
option target /
option device /dev/sda1
option fstype ext4
option options rw,sync
option enabled 1
option enabled_fsck 0
</code></pre></div></div>
<p><strong>Redémarrage et vérification</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>reboot
</code></pre></div></div>
<p>Lorsque vous redémarrez, vous devriez maintenant exécuter OpenWrt depuis votre clé USB.</p>
<p>Vérifiez vos montages actuels avec cette commande :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mount
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/dev/root on /rom type ext4 (ro,noatime)
proc on /proc type proc (rw,nosuid,nodev,noexec,noatime)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,noatime)
tmpfs on /tmp type tmpfs (rw,nosuid,nodev,noatime)
/dev/sda1 on / type ext4 (rw,sync,relatime,data=ordered)
/dev/mmcblk0p1 on /boot type vfat (rw,noatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro)
tmpfs on /dev type tmpfs (rw,nosuid,relatime,size=512k,mode=755)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,mode=600,ptmxmode=000)
debugfs on /sys/kernel/debug type debugfs (rw,noatime)
</code></pre></div></div>
<p>Voyez combien despace vous avez créé pour les paquets avec cette commande :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>df -h
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Filesystem Size Used Available Use% Mounted on
/dev/root 252.0M 14.4M 232.4M 6% /rom
tmpfs 218.7M 76.0K 218.6M 0% /tmp
/dev/sda1 3.6G 14.4M 3.4G 0% /
/dev/mmcblk0p1 19.9M 16.1M 3.8M 81% /boot
tmpfs 512.0K 0 512.0K 0% /dev
</code></pre></div></div>
<h3 id="wifi-usb-ralink-rt5370">Wifi USB Ralink RT5370</h3>
<p><strong>Installer les pilotes du dongle Wifi USB Ralink RT5370</strong><br />
<a href="https://forum.openwrt.org/t/rpi-3-ralink-rt5370-usb-wifi-adapter-solved/87382/2">RPi 3 + Ralink RT5370 USB wifi adapter [SOLVED]</a><br />
Installer les drivers</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opkg update <span class="o">&amp;&amp;</span> opkg <span class="nb">install </span>kmod-rt2800-lib kmod-rt2800-usb kmod-rt2x00-lib kmod-rt2x00-usb
</code></pre></div></div>
<p>Redémarrer le routeur pour la prise en compte <code class="language-plaintext highlighter-rouge">reboot</code><br />
Vérification</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>root@OpenWrt:~# ip a
<span class="o">[</span>...]
3: wlan0: &lt;BROADCAST,MULTICAST&gt; mtu 1500 qdisc noop state DOWN qlen 1000
<span class="nb">link</span>/ether 00:0f:00:3b:2e:31 brd ff:ff:ff:ff:ff:ff
<span class="o">[</span>...]
</code></pre></div></div>
<p>Par le web <strong>Network → Interfaces LAN</strong><br />
<img src="/images/openwrt09-a.png" alt="openwrt" width="600" /><br />
Cliquez sur <strong>Edit</strong>, vérifiez ou modifiez <br />
<img src="/images/openwrt09.png" alt="openwrt" width="600" /><br />
<img src="/images/openwrt10.png" alt="openwrt" width="600" /><br />
<img src="/images/openwrt10a.png" alt="openwrt" width="600" /></p>
<h2 id="routeur-4g">Routeur 4G</h2>
<h3 id="connexion-usb-dun-smartphone">Connexion USB dun smartphone</h3>
<ul>
<li><a href="https://openwrt.org/docs/guide-user/network/wan/smartphone.usb.tethering">Smartphone USB tethering</a></li>
</ul>
<p>Le <strong>tethering</strong> USB est utilisé pour connecter votre routeur OpenWrt à Internet en utilisant votre smartphone. Cest plus pratique et plus performant (latence plus faible) que de transformer votre smartphone en point daccès et de lutiliser. Cela représente également une charge CPU moindre pour votre téléphone, recharge votre téléphone et vous permet de faire des choses avec votre routeur OpenWrt que vous ne pouvez pas faire avec votre téléphone, comme connecter facilement plusieurs appareils, avec ou sans fil, les uns aux autres et à Internet. Afin de maximiser les performances, vous devez désactiver le Wi-Fi et le Bluetooth de votre téléphone connecté.</p>
<p>Connexion SSH root</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh root@192.168.0.1
</code></pre></div></div>
<p>Fournir le support du tethering USB pour Android 8/10 avec RNDIS :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opkg update &amp;&amp; opkg install kmod-usb-net-rndis
</code></pre></div></div>
<p><strong>Connecter le smartphone au port USB du routeur</strong> à laide du câble USB, puis activez loption USB Tethering dans les paramètres dAndroid. Activez les options de développement du téléphone <strong>Trouvez les informations de construction dans le menu À propos du téléphone, et appuyez rapidement sur 7 x</strong>. Il y a une configuration USB par défaut : USB Tethering. <br />
Paramètres → Réseau et Internet<br />
<img src="/images/openwrt11.png" alt="openwrt" height="200" /> <img src="/images/openwrt12.png" alt="openwrt" height="200" /></p>
<p>Le téléphone activera immédiatement le mode Tethering USB lorsquil sera branché sur un routeur ( ou un ordinateur portable) configuré, sans autre commande. Cependant, il est nécessaire denlever le verrouillage de lécran du téléphone. Un téléphone verrouillé ne pourra pas démarrer le mode de connexion USB par lui-même.</p>
<p>Pour les IPhones, vous devrez peut-être désactiver et réactiver le paramètre Personal Hotspot/Allow Others to Join sur lIPhone pour forcer le client DHCP dOpenWrt à obtenir une adresse IP de linterface eth1 de lIPhone. Désactiver et réactiver le paramètre Personal Hotspot/Allow Others to Join sur lIPhone est également nécessaire si vous déconnectez lIPhone du port USB dOpenWrt et le reconnectez plus tard, à moins que vous ne mettiez en cache les Trust records (voir la section watchdog et/ou le lien github de LeJeko ci-dessous).</p>
<h3 id="activer-tethering-sur-le-routeur">Activer “Tethering” sur le routeur</h3>
<p><strong>En ligne de commande</strong></p>
<p>Sur le routeur, entrez :</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Activez le tethering</span>
uci <span class="nb">set </span>network.wan.ifname<span class="o">=</span><span class="s2">"usb0"</span>
uci <span class="nb">set </span>network.wan6.ifname<span class="o">=</span><span class="s2">"usb0"</span>
uci commit network
/etc/init.d/network restart
</code></pre></div></div>
<blockquote>
<p>Pour les IPhones, remplacez le nom de linterface usb* par eth* selon le routeur.</p>
</blockquote>
<p>Tout devrait fonctionner à ce stade.</p>
<h3 id="point-daccès-wifi">Point daccès Wifi</h3>
<p><em>Pour activer les connexions sans fil au routeur, allez dans Network, Wireless et définissez puis activez les interfaces.<br />
Configurer le wifi en point daccès par le web</em></p>
<p>Allez sur <strong>Network → Wireless</strong></p>
<p>Supprimer lexistant<br />
<img src="/images/openwrt21b.png" alt="openwrt" width="400" /></p>
<p>ajoutez un nouveau SSID appelé “guest” associé à un réseau appelé “invite” également. <br />
<img src="/images/openwrt22.png" alt="openwrt" width="600" /><br />
Spécifier le code pays (dans mon cas, la France) afin que votre appareil soit conforme aux règles internationales établies (Advanced settings).<br />
<img src="/images/openwrt23a.png" alt="openwrt" width="600" /><br />
Configuer la sécurité wpa2<br />
<img src="/images/openwrt24a.png" alt="openwrt" width="600" /></p>
<p>Cliquer sur “<strong>Save</strong>” puis “<strong>Save &amp; Apply</strong>” et vous devriez maintenant avoir un tout nouveau SSID (voir ci-dessous). <br />
<img src="/images/openwrt25.png" alt="openwrt" width="600" /></p>
<p><strong>Interface Web (Par défaut)</strong></p>
<p>Allez dans <strong>Network → Interfaces</strong>. Créez une nouvelle interface (<strong>Add new interface</strong>) appelée <strong>TetheringWAN</strong>, et associez-y le nouveau périphérique réseau <em>usb0</em> (ou dans certains cas <em>eth1</em>, vérifiez ce que le journal indique dans votre cas), définissez le protocole en mode <strong>client DHCP</strong> ou en mode <strong>client DHCPv6</strong> si le FAI attribue lIPv6, et sous longlet Paramètres du pare-feu, placez-le dans la zone WAN. Enregistrez les modifications.</p>
<p><img src="/images/openwrt13.png" alt="openwrt" width="400" /><br />
Créer linterface <strong>TetheringWAN</strong>.<br />
<img src="/images/openwrt17.png" alt="openwrt" width="400" /><br />
onglet <strong>Firewall Settings</strong> de lassistant de création dinterface. Il est très important de le définir comme <strong>WAN</strong>.<br />
Cliquez sur <strong>Save</strong> puis <strong>Save &amp; Apply</strong><br />
<img src="/images/openwrt14.png" alt="openwrt" width="600" /></p>
<p><strong>TRES IMPORTANT:</strong><br />
Il faut <u>supprimer le gateway et les adresses dns du routeur</u> et vérifier ou passer ladresse ip fixe en 192.168.0.1 (Static address)</p>
<p><strong>Network → Interfaces Lan Edit → General Settings</strong> <br />
<img src="/images/openwrt18a.png" alt="openwrt" width="400" /><br />
“save”<br />
<img src="/images/openwrt21.png" alt="openwrt" width="400" /><br />
<img src="/images/openwrt21a.png" alt="openwrt" width="400" /></p>
<p>Interface <strong>Invite</strong>, allez sur <strong>Network → Interface &amp;rarr. INVITE Edit</strong><br />
<img src="/images/openwrt26.png" alt="openwrt" width="600" /></p>
<p>Sous <strong>General Settings</strong>, changer the protocol de “Unmanaged” to “Static address” <br />
<img src="/images/openwrt26a.png" alt="openwrt" width="400" /></p>
<p>Puis cliquer sur “<strong>Switch protocol</strong>” et configurer adresse IP et netmask de linterface Guest<br />
<img src="/images/openwrt26b.png" alt="openwrt" width="400" /></p>
<p class="warning">ATTENTION !! Il faut un autre réseau que celui du lan :<br />
LAN → 192.168.0.1<br />
INVITE → 192.168.55.1</p>
<p>Cliquer sur longlet <strong>Physical Settings</strong> puis valider Bridge interfaces interface wlan0<br />
<img src="/images/openwrt26c.png" alt="openwrt" width="400" /><br />
Onglet <strong>DHCP Server</strong> , cliquez sur <strong>Setuo DHCP Server</strong> à linterface <br />
<img src="/images/openwrt26d.png" alt="openwrt" width="400" /><br />
Cliquez sur <strong>Save</strong> puis “<strong>Save and Apply</strong></p>
<h3 id="network--firewall">Network → Firewall</h3>
<p><img src="/images/openwrt34.png" alt="openwrt" width="600" /><br />
Cliquer sur “<strong>Add</strong>” pour ajouter “Invite”<br />
<img src="/images/openwrt34a.png" alt="openwrt" width="600" /><br />
Cliquer sur <strong>Save</strong> puis sur <strong>*Save &amp; Apply</strong><br />
Vos retrouvez léquivalent au contexte ci-dessous<br />
<img src="/images/openwrt29b.png" alt="openwrt" width="600" /></p>
<p class="info"><strong>Les options input et output</strong> définissent les politiques par défaut pour le trafic entrant et sortant de cette zone tandis que loption forward décrit la politique pour le trafic transféré entre les différents réseaux de la zone. Les réseaux couverts spécifient les réseaux disponibles qui sont membres de cette zone.<br />
<img src="/images/openwrt30.png" alt="openwrt" width="200" /> <img src="/images/openwrt31.png" alt="openwrt" width="200" /> <img src="/images/openwrt32.png" alt="openwrt" width="200" /><br />
<strong>Les options ci-dessous</strong> contrôlent les politiques de transfert entre cette zone (wan) et les autres zones. Les zones de destination couvrent le trafic transféré provenant de wan. Les zones sources correspondent au trafic transféré provenant dautres zones et destiné à wan. La règle de transfert est unidirectionnelle, cest-à-dire quun transfert de lan vers wan nimplique pas une permission de transfert de wan vers lan également.<br />
<img src="/images/openwrt30a.png" alt="openwrt" width="200" /> <img src="/images/openwrt31a.png" alt="openwrt" width="200" /> <img src="/images/openwrt32a.png" alt="openwrt" width="200" /></p>
<h2 id="fichiers-configuration-openwrt">Fichiers configuration OpenWRT</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>BusyBox v1.30.1 () built-in shell (ash)
_______ ________ __
| |.-----.-----.-----.| | | |.----.| |_
| - || _ | -__| || | | || _|| _|
|_______|| __|_____|__|__||________||__| |____|
|__| W I R E L E S S F R E E D O M
-----------------------------------------------------
OpenWrt 19.07.7, r11306-c4a6851c72
-----------------------------------------------------
root@OpenWrt:/# ls /etc/config
dhcp firewall luci rpcd ucitrack wireless
dropbear fstab network system uhttpd
</code></pre></div></div>
<h3 id="lan-eth0-1921680024">Lan eth0 192.168.0.0/24</h3>
<p>Situés sous <code class="language-plaintext highlighter-rouge">/etc/config/</code><br />
<img src="/images/openwrt33.png" alt="openwrt" width="500" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/etc/config/network
</code></pre></div></div>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>config interface <span class="s1">'loopback'</span>
option ifname <span class="s1">'lo'</span>
option proto <span class="s1">'static'</span>
option ipaddr <span class="s1">'127.0.0.1'</span>
option netmask <span class="s1">'255.0.0.0'</span>
config globals <span class="s1">'globals'</span>
option ula_prefix <span class="s1">'fdca:3e71:c28a::/48'</span>
config interface <span class="s1">'lan'</span>
option <span class="nb">type</span> <span class="s1">'bridge'</span>
option ifname <span class="s1">'eth0'</span>
option proto <span class="s1">'static'</span>
option ipaddr <span class="s1">'192.168.0.1'</span>
option netmask <span class="s1">'255.255.255.0'</span>
option ip6assign <span class="s1">'60'</span>
option gateway <span class="s1">'192.168.0.254'</span>
list dns <span class="s1">'1.1.1.1'</span>
config interface <span class="s1">'Invite'</span>
option proto <span class="s1">'static'</span>
option netmask <span class="s1">'255.255.255.0'</span>
option <span class="nb">type</span> <span class="s1">'bridge'</span>
option ipaddr <span class="s1">'192.168.55.1'</span>
config interface <span class="s1">'TetheringWAN'</span>
option ifname <span class="s1">'usb0'</span>
option proto <span class="s1">'dhcp'</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/etc/config/wireless
</code></pre></div></div>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>config wifi-device <span class="s1">'radio0'</span>
option <span class="nb">type</span> <span class="s1">'mac80211'</span>
option hwmode <span class="s1">'11g'</span>
option path <span class="s1">'platform/soc/20980000.usb/usb1/1-1/1-1.2/1-1.2:1.0'</span>
option htmode <span class="s1">'HT20'</span>
option channel <span class="s1">'8'</span>
option country <span class="s1">'FR'</span>
config wifi-iface <span class="s1">'wifinet0'</span>
option device <span class="s1">'radio0'</span>
option mode <span class="s1">'ap'</span>
option ssid <span class="s1">'YanWrt'</span>
option network <span class="s1">'Invite'</span>
option key <span class="s1">'xxxxxxxxxxxxxxxxxxxx'</span>
option encryption <span class="s1">'psk2'</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/etc/config/dhcp
</code></pre></div></div>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>config dnsmasq
option domainneeded <span class="s1">'1'</span>
option boguspriv <span class="s1">'1'</span>
option filterwin2k <span class="s1">'0'</span>
option localise_queries <span class="s1">'1'</span>
option rebind_protection <span class="s1">'1'</span>
option rebind_localhost <span class="s1">'1'</span>
option <span class="nb">local</span> <span class="s1">'/lan/'</span>
option domain <span class="s1">'lan'</span>
option expandhosts <span class="s1">'1'</span>
option nonegcache <span class="s1">'0'</span>
option authoritative <span class="s1">'1'</span>
option readethers <span class="s1">'1'</span>
option leasefile <span class="s1">'/tmp/dhcp.leases'</span>
option resolvfile <span class="s1">'/tmp/resolv.conf.auto'</span>
option nonwildcard <span class="s1">'1'</span>
option localservice <span class="s1">'1'</span>
config dhcp <span class="s1">'lan'</span>
option interface <span class="s1">'lan'</span>
option start <span class="s1">'100'</span>
option limit <span class="s1">'150'</span>
option leasetime <span class="s1">'12h'</span>
option dhcpv6 <span class="s1">'server'</span>
option ra <span class="s1">'server'</span>
option ra_management <span class="s1">'1'</span>
config dhcp <span class="s1">'wan'</span>
option interface <span class="s1">'wan'</span>
option ignore <span class="s1">'1'</span>
config odhcpd <span class="s1">'odhcpd'</span>
option maindhcp <span class="s1">'0'</span>
option leasefile <span class="s1">'/tmp/hosts/odhcpd'</span>
option leasetrigger <span class="s1">'/usr/sbin/odhcpd-update'</span>
option loglevel <span class="s1">'4'</span>
config dhcp <span class="s1">'Invite'</span>
option start <span class="s1">'100'</span>
option leasetime <span class="s1">'12h'</span>
option limit <span class="s1">'150'</span>
option interface <span class="s1">'Invite'</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/etc/config/firewall
</code></pre></div></div>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>config defaults
option input <span class="s1">'ACCEPT'</span>
option output <span class="s1">'ACCEPT'</span>
option forward <span class="s1">'REJECT'</span>
option synflood_protect <span class="s1">'1'</span>
config zone
option name <span class="s1">'lan'</span>
list network <span class="s1">'lan'</span>
option input <span class="s1">'ACCEPT'</span>
option output <span class="s1">'ACCEPT'</span>
option forward <span class="s1">'ACCEPT'</span>
config zone
option name <span class="s1">'wan'</span>
option input <span class="s1">'REJECT'</span>
option output <span class="s1">'ACCEPT'</span>
option forward <span class="s1">'REJECT'</span>
option masq <span class="s1">'1'</span>
option mtu_fix <span class="s1">'1'</span>
option network <span class="s1">'wan wan6 TetheringWAN'</span>
config forwarding
option src <span class="s1">'lan'</span>
option dest <span class="s1">'wan'</span>
config rule
option name <span class="s1">'Allow-DHCP-Renew'</span>
option src <span class="s1">'wan'</span>
option proto <span class="s1">'udp'</span>
option dest_port <span class="s1">'68'</span>
option target <span class="s1">'ACCEPT'</span>
option family <span class="s1">'ipv4'</span>
config rule
option name <span class="s1">'Allow-Ping'</span>
option src <span class="s1">'wan'</span>
option proto <span class="s1">'icmp'</span>
option icmp_type <span class="s1">'echo-request'</span>
option family <span class="s1">'ipv4'</span>
option target <span class="s1">'ACCEPT'</span>
config rule
option name <span class="s1">'Allow-IGMP'</span>
option src <span class="s1">'wan'</span>
option proto <span class="s1">'igmp'</span>
option family <span class="s1">'ipv4'</span>
option target <span class="s1">'ACCEPT'</span>
config rule
option name <span class="s1">'Allow-DHCPv6'</span>
option src <span class="s1">'wan'</span>
option proto <span class="s1">'udp'</span>
option src_ip <span class="s1">'fc00::/6'</span>
option dest_ip <span class="s1">'fc00::/6'</span>
option dest_port <span class="s1">'546'</span>
option family <span class="s1">'ipv6'</span>
option target <span class="s1">'ACCEPT'</span>
config rule
option name <span class="s1">'Allow-MLD'</span>
option src <span class="s1">'wan'</span>
option proto <span class="s1">'icmp'</span>
option src_ip <span class="s1">'fe80::/10'</span>
list icmp_type <span class="s1">'130/0'</span>
list icmp_type <span class="s1">'131/0'</span>
list icmp_type <span class="s1">'132/0'</span>
list icmp_type <span class="s1">'143/0'</span>
option family <span class="s1">'ipv6'</span>
option target <span class="s1">'ACCEPT'</span>
config rule
option name <span class="s1">'Allow-ICMPv6-Input'</span>
option src <span class="s1">'wan'</span>
option proto <span class="s1">'icmp'</span>
list icmp_type <span class="s1">'echo-request'</span>
list icmp_type <span class="s1">'echo-reply'</span>
list icmp_type <span class="s1">'destination-unreachable'</span>
list icmp_type <span class="s1">'packet-too-big'</span>
list icmp_type <span class="s1">'time-exceeded'</span>
list icmp_type <span class="s1">'bad-header'</span>
list icmp_type <span class="s1">'unknown-header-type'</span>
list icmp_type <span class="s1">'router-solicitation'</span>
list icmp_type <span class="s1">'neighbour-solicitation'</span>
list icmp_type <span class="s1">'router-advertisement'</span>
list icmp_type <span class="s1">'neighbour-advertisement'</span>
option limit <span class="s1">'1000/sec'</span>
option family <span class="s1">'ipv6'</span>
option target <span class="s1">'ACCEPT'</span>
config rule
option name <span class="s1">'Allow-ICMPv6-Forward'</span>
option src <span class="s1">'wan'</span>
option dest <span class="s1">'*'</span>
option proto <span class="s1">'icmp'</span>
list icmp_type <span class="s1">'echo-request'</span>
list icmp_type <span class="s1">'echo-reply'</span>
list icmp_type <span class="s1">'destination-unreachable'</span>
list icmp_type <span class="s1">'packet-too-big'</span>
list icmp_type <span class="s1">'time-exceeded'</span>
list icmp_type <span class="s1">'bad-header'</span>
list icmp_type <span class="s1">'unknown-header-type'</span>
option limit <span class="s1">'1000/sec'</span>
option family <span class="s1">'ipv6'</span>
option target <span class="s1">'ACCEPT'</span>
config rule
option name <span class="s1">'Allow-IPSec-ESP'</span>
option src <span class="s1">'wan'</span>
option dest <span class="s1">'lan'</span>
option proto <span class="s1">'esp'</span>
option target <span class="s1">'ACCEPT'</span>
config rule
option name <span class="s1">'Allow-ISAKMP'</span>
option src <span class="s1">'wan'</span>
option dest <span class="s1">'lan'</span>
option dest_port <span class="s1">'500'</span>
option proto <span class="s1">'udp'</span>
option target <span class="s1">'ACCEPT'</span>
config include
option path <span class="s1">'/etc/firewall.user'</span>
config zone
option name <span class="s1">'ZoneWifi'</span>
option input <span class="s1">'ACCEPT'</span>
option forward <span class="s1">'ACCEPT'</span>
option network <span class="s1">'Invite'</span>
option output <span class="s1">'ACCEPT'</span>
config forwarding
option dest <span class="s1">'wan'</span>
option src <span class="s1">'ZoneWifi'</span>
</code></pre></div></div>
<hr />
<h3 id="lan-eth0-1921682024">Lan eth0 192.168.2.0/24</h3>
<p>Modifier /etc/config/network <br />
Remplacer dans <code class="language-plaintext highlighter-rouge">config interface 'lan'</code> : <br />
<code class="language-plaintext highlighter-rouge">option ipaddr '192.168.0.1'</code><code class="language-plaintext highlighter-rouge">option ipaddr '192.168.2.1'</code></p>
<p>Redémarrer le routeur</p>
<h2 id="wireguard">Wireguard</h2>
<p><em>Installer wireguard Mullvad sur le routeur</em><br />
<a href="http://lxcdeb:8080/2021/04/16/WireGuard_sur_un_routeur.html">OpenWrt - WireGuard sur un routeur 4G Raspberry Pi</a></p>
<h2 id="upgrade-openwrt">Upgrade OpenWRT</h2>
<p><a href="https://doc.huc.fr.eu.org/fr/sys/openwrt/sysupgrade/">OpenWRT : Gérer correctement le processus de mise à niveau (sysupgrade)</a></p>
<p>Le procédé suivant explique pas-à-pas la mise à niveau tout en mode CLI !</p>
<p>La première chose à laquelle nous veillons est dinstaller loutil curl, car par défaut le binaire wget nativement installé ne supporte pas TLS.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opkg install curl
</code></pre></div></div>
<p>Ensuite, nous récupèrons ce script fort utile opkgscript.sh :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl -O https://raw.githubusercontent.com/richb-hanover/OpenWrtScripts/master/opkgscript.sh
</code></pre></div></div>
<p>Et, nous donnons les droits dexécution nécessaire :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chmod 0700 opkgscript.sh
</code></pre></div></div>
<p>on sauvegarde la liste des paquets installés - pour pouvoir restaurer après la mise à niveau système :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./opkgscript.sh -v write
# Saving package list to /etc/config/opkg.installed
</code></pre></div></div>
<p>Le script écrit la liste dans un fichier /etc/config/opkg.installed.</p>
<p>Récupèrons la nouvelle version du <a href="https://openwrt.org/toh/raspberry_pi_foundation/raspberry_pi">firmware pour Raspberry PI B+</a></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>v="21.02.0"
curl -O http://downloads.openwrt.org/releases/"${v}"/targets/bcm27xx/bcm2708/openwrt-"${v}"-bcm27xx-bcm2708-rpi-ext4-sysupgrade.img.gz
</code></pre></div></div>
</div>
<div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2021-04-17T00:00:00+02:00"><!-- start custom article footer snippet -->
<!-- end custom article footer snippet -->
<!--
<div align="right"><a type="application/rss+xml" href="/feed.xml" title="S'abonner"><i class="fa fa-rss fa-2x"></i></a>
&emsp;</div>
-->
</footer>
<div class="article__section-navigator clearfix"><div class="previous"><span>PRÉCÉDENT</span><a href="/2021/04/16/Linux-Ajout-Carte-Reseau.html">Linux netctl ajout et configuration carte réseau ethernet + routage</a></div><div class="next"><span>SUIVANT</span><a href="/2021/05/04/Installer_serveur_debian_virtuel_QEMU_KVM-sur-poste-archlinux.html">Installer un serveur debian virtuel (debsrv) sur un poste archlinux</a></div></div></div>
</div>
<script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
$(function() {
var $this ,$scroll;
var $articleContent = $('.js-article-content');
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
var scroll = hasSidebar ? '.js-page-main' : 'html, body';
$scroll = $(scroll);
$articleContent.find('.highlight').each(function() {
$this = $(this);
$this.attr('data-lang', $this.find('code').attr('data-lang'));
});
$articleContent.find('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]').each(function() {
$this = $(this);
$this.append($('<a class="anchor d-print-none" aria-hidden="true"></a>').html('<i class="fas fa-anchor"></i>'));
});
$articleContent.on('click', '.anchor', function() {
$scroll.scrollToAnchor('#' + $(this).parent().attr('id'), 400);
});
});
});
})();
</script>
</div><section class="page__comments d-print-none"></section></article><!-- start custom main bottom snippet -->
<!-- end custom main bottom snippet -->
</div>
</div></div></div></div>
</div><script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
var $body = $('body'), $window = $(window);
var $pageRoot = $('.js-page-root'), $pageMain = $('.js-page-main');
var activeCount = 0;
function modal(options) {
var $root = this, visible, onChange, hideWhenWindowScroll = false;
var scrollTop;
function setOptions(options) {
var _options = options || {};
visible = _options.initialVisible === undefined ? false : show;
onChange = _options.onChange;
hideWhenWindowScroll = _options.hideWhenWindowScroll;
}
function init() {
setState(visible);
}
function setState(isShow) {
if (isShow === visible) {
return;
}
visible = isShow;
if (visible) {
activeCount++;
scrollTop = $(window).scrollTop() || $pageMain.scrollTop();
$root.addClass('modal--show');
$pageMain.scrollTop(scrollTop);
activeCount === 1 && ($pageRoot.addClass('show-modal'), $body.addClass('of-hidden'));
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.on('scroll', hide);
$window.on('keyup', handleKeyup);
} else {
activeCount > 0 && activeCount--;
$root.removeClass('modal--show');
$window.scrollTop(scrollTop);
activeCount === 0 && ($pageRoot.removeClass('show-modal'), $body.removeClass('of-hidden'));
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.off('scroll', hide);
$window.off('keyup', handleKeyup);
}
onChange && onChange(visible);
}
function show() {
setState(true);
}
function hide() {
setState(false);
}
function handleKeyup(e) {
// Char Code: 27 ESC
if (e.which === 27) {
hide();
}
}
setOptions(options);
init();
return {
show: show,
hide: hide,
$el: $root
};
}
$.fn.modal = modal;
});
})();
</script><div class="modal modal--overflow page__search-modal d-print-none js-page-search-modal"><script>
(function () {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
// search panel
var search = (window.search || (window.search = {}));
var useDefaultSearchBox = window.useDefaultSearchBox === undefined ?
true : window.useDefaultSearchBox ;
var $searchModal = $('.js-page-search-modal');
var $searchToggle = $('.js-search-toggle');
var searchModal = $searchModal.modal({ onChange: handleModalChange, hideWhenWindowScroll: true });
var modalVisible = false;
search.searchModal = searchModal;
var $searchBox = null;
var $searchInput = null;
var $searchClear = null;
function getModalVisible() {
return modalVisible;
}
search.getModalVisible = getModalVisible;
function handleModalChange(visible) {
modalVisible = visible;
if (visible) {
search.onShow && search.onShow();
useDefaultSearchBox && $searchInput[0] && $searchInput[0].focus();
} else {
search.onShow && search.onHide();
useDefaultSearchBox && $searchInput[0] && $searchInput[0].blur();
setTimeout(function() {
useDefaultSearchBox && ($searchInput.val(''), $searchBox.removeClass('not-empty'));
search.clear && search.clear();
window.pageAsideAffix && window.pageAsideAffix.refresh();
}, 400);
}
}
$searchToggle.on('click', function() {
modalVisible ? searchModal.hide() : searchModal.show();
});
// Char Code: 83 S, 191 /
$(window).on('keyup', function(e) {
if (!modalVisible && !window.isFormElement(e.target || e.srcElement) && (e.which === 83 || e.which === 191)) {
modalVisible || searchModal.show();
}
});
if (useDefaultSearchBox) {
$searchBox = $('.js-search-box');
$searchInput = $searchBox.children('input');
$searchClear = $searchBox.children('.js-icon-clear');
search.getSearchInput = function() {
return $searchInput.get(0);
};
search.getVal = function() {
return $searchInput.val();
};
search.setVal = function(val) {
$searchInput.val(val);
};
$searchInput.on('focus', function() {
$(this).addClass('focus');
});
$searchInput.on('blur', function() {
$(this).removeClass('focus');
});
$searchInput.on('input', window.throttle(function() {
var val = $(this).val();
if (val === '' || typeof val !== 'string') {
search.clear && search.clear();
} else {
$searchBox.addClass('not-empty');
search.onInputNotEmpty && search.onInputNotEmpty(val);
}
}, 400));
$searchClear.on('click', function() {
$searchInput.val(''); $searchBox.removeClass('not-empty');
search.clear && search.clear();
});
}
});
})();
</script><div class="search search--dark">
<div class="main">
<div class="search__header">Recherche</div>
<div class="search-bar">
<div class="search-box js-search-box">
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
<input id="search-input" type="text" />
<div class="search-box__icon-clear js-icon-clear">
<a><i class="fas fa-times"></i></a>
</div>
</div>
<button class="button button--theme-dark button--pill search__cancel js-search-toggle">
Annuler</button>
</div>
<div id="results-container" class="search-result js-search-result"></div>
</div>
</div>
<!-- Script pointing to search-script.js -->
<script>/*!
* Simple-Jekyll-Search
* Copyright 2015-2020, Christian Fei
* Licensed under the MIT License.
*/
(function(){
'use strict'
var _$Templater_7 = {
compile: compile,
setOptions: setOptions
}
const options = {}
options.pattern = /\{(.*?)\}/g
options.template = ''
options.middleware = function () {}
function setOptions (_options) {
options.pattern = _options.pattern || options.pattern
options.template = _options.template || options.template
if (typeof _options.middleware === 'function') {
options.middleware = _options.middleware
}
}
function compile (data) {
return options.template.replace(options.pattern, function (match, prop) {
const value = options.middleware(prop, data[prop], options.template)
if (typeof value !== 'undefined') {
return value
}
return data[prop] || match
})
}
'use strict';
function fuzzysearch (needle, haystack) {
var tlen = haystack.length;
var qlen = needle.length;
if (qlen > tlen) {
return false;
}
if (qlen === tlen) {
return needle === haystack;
}
outer: for (var i = 0, j = 0; i < qlen; i++) {
var nch = needle.charCodeAt(i);
while (j < tlen) {
if (haystack.charCodeAt(j++) === nch) {
continue outer;
}
}
return false;
}
return true;
}
var _$fuzzysearch_1 = fuzzysearch;
'use strict'
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
function FuzzySearchStrategy () {
this.matches = function (string, crit) {
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
}
}
'use strict'
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
function LiteralSearchStrategy () {
this.matches = function (str, crit) {
if (!str) return false
str = str.trim().toLowerCase()
crit = crit.trim().toLowerCase()
return crit.split(' ').filter(function (word) {
return str.indexOf(word) >= 0
}).length === crit.split(' ').length
}
}
'use strict'
var _$Repository_4 = {
put: put,
clear: clear,
search: search,
setOptions: __setOptions_4
}
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
function NoSort () {
return 0
}
const data = []
let opt = {}
opt.fuzzy = false
opt.limit = 10
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = NoSort
opt.exclude = []
function put (data) {
if (isObject(data)) {
return addObject(data)
}
if (isArray(data)) {
return addArray(data)
}
return undefined
}
function clear () {
data.length = 0
return data
}
function isObject (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
}
function isArray (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
}
function addObject (_data) {
data.push(_data)
return data
}
function addArray (_data) {
const added = []
clear()
for (let i = 0, len = _data.length; i < len; i++) {
if (isObject(_data[i])) {
added.push(addObject(_data[i]))
}
}
return added
}
function search (crit) {
if (!crit) {
return []
}
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
}
function __setOptions_4 (_opt) {
opt = _opt || {}
opt.fuzzy = _opt.fuzzy || false
opt.limit = _opt.limit || 10
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = _opt.sort || NoSort
opt.exclude = _opt.exclude || []
}
function findMatches (data, crit, strategy, opt) {
const matches = []
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
const match = findMatchesInObject(data[i], crit, strategy, opt)
if (match) {
matches.push(match)
}
}
return matches
}
function findMatchesInObject (obj, crit, strategy, opt) {
for (const key in obj) {
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
return obj
}
}
}
function isExcluded (term, excludedTerms) {
for (let i = 0, len = excludedTerms.length; i < len; i++) {
const excludedTerm = excludedTerms[i]
if (new RegExp(excludedTerm).test(term)) {
return true
}
}
return false
}
/* globals ActiveXObject:false */
'use strict'
var _$JSONLoader_2 = {
load: load
}
function load (location, callback) {
const xhr = getXHR()
xhr.open('GET', location, true)
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
xhr.send()
}
function createStateChangeListener (xhr, callback) {
return function () {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
callback(null, JSON.parse(xhr.responseText))
} catch (err) {
callback(err, null)
}
}
}
}
function getXHR () {
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
}
'use strict'
var _$OptionsValidator_3 = function OptionsValidator (params) {
if (!validateParams(params)) {
throw new Error('-- OptionsValidator: required options missing')
}
if (!(this instanceof OptionsValidator)) {
return new OptionsValidator(params)
}
const requiredOptions = params.required
this.getRequiredOptions = function () {
return requiredOptions
}
this.validate = function (parameters) {
const errors = []
requiredOptions.forEach(function (requiredOptionName) {
if (typeof parameters[requiredOptionName] === 'undefined') {
errors.push(requiredOptionName)
}
})
return errors
}
function validateParams (params) {
if (!params) {
return false
}
return typeof params.required !== 'undefined' && params.required instanceof Array
}
}
'use strict'
var _$utils_9 = {
merge: merge,
isJSON: isJSON
}
function merge (defaultParams, mergeParams) {
const mergedOptions = {}
for (const option in defaultParams) {
mergedOptions[option] = defaultParams[option]
if (typeof mergeParams[option] !== 'undefined') {
mergedOptions[option] = mergeParams[option]
}
}
return mergedOptions
}
function isJSON (json) {
try {
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
return true
}
return false
} catch (err) {
return false
}
}
var _$src_8 = {};
(function (window) {
'use strict'
let options = {
searchInput: null,
resultsContainer: null,
json: [],
success: Function.prototype,
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
templateMiddleware: Function.prototype,
sortMiddleware: function () {
return 0
},
noResultsText: 'No results found',
limit: 10,
fuzzy: false,
debounceTime: null,
exclude: []
}
let debounceTimerHandle
const debounce = function (func, delayMillis) {
if (delayMillis) {
clearTimeout(debounceTimerHandle)
debounceTimerHandle = setTimeout(func, delayMillis)
} else {
func.call()
}
}
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
/* removed: const _$Templater_7 = require('./Templater') */;
/* removed: const _$Repository_4 = require('./Repository') */;
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
const optionsValidator = _$OptionsValidator_3({
required: requiredOptions
})
/* removed: const _$utils_9 = require('./utils') */;
window.SimpleJekyllSearch = function (_options) {
const errors = optionsValidator.validate(_options)
if (errors.length > 0) {
throwError('You must specify the following required options: ' + requiredOptions)
}
options = _$utils_9.merge(options, _options)
_$Templater_7.setOptions({
template: options.searchResultTemplate,
middleware: options.templateMiddleware
})
_$Repository_4.setOptions({
fuzzy: options.fuzzy,
limit: options.limit,
sort: options.sortMiddleware,
exclude: options.exclude
})
if (_$utils_9.isJSON(options.json)) {
initWithJSON(options.json)
} else {
initWithURL(options.json)
}
const rv = {
search: search
}
typeof options.success === 'function' && options.success.call(rv)
return rv
}
function initWithJSON (json) {
_$Repository_4.put(json)
registerInput()
}
function initWithURL (url) {
_$JSONLoader_2.load(url, function (err, json) {
if (err) {
throwError('failed to get JSON (' + url + ')')
}
initWithJSON(json)
})
}
function emptyResultsContainer () {
options.resultsContainer.innerHTML = ''
}
function appendToResultsContainer (text) {
options.resultsContainer.innerHTML += text
}
function registerInput () {
options.searchInput.addEventListener('input', function (e) {
if (isWhitelistedKey(e.which)) {
emptyResultsContainer()
debounce(function () { search(e.target.value) }, options.debounceTime)
}
})
}
function search (query) {
if (isValidQuery(query)) {
emptyResultsContainer()
render(_$Repository_4.search(query), query)
}
}
function render (results, query) {
const len = results.length
if (len === 0) {
return appendToResultsContainer(options.noResultsText)
}
for (let i = 0; i < len; i++) {
results[i].query = query
appendToResultsContainer(_$Templater_7.compile(results[i]))
}
}
function isValidQuery (query) {
return query && query.length > 0
}
function isWhitelistedKey (key) {
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
}
function throwError (message) {
throw new Error('SimpleJekyllSearch --- ' + message)
}
})(window)
}());
</script>
<!-- Configuration -->
<script>
SimpleJekyllSearch({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
noResultsText: '<p>Aucun résultat!</p>',
json: '/search.json',
searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{title}</a>&nbsp;(Création {create})</li>'
})
</script>
</div></div>
<script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function scrollToAnchor(anchor, duration, callback) {
var $root = this;
$root.animate({ scrollTop: $(anchor).position().top }, duration, function() {
window.history.replaceState(null, '', window.location.href.split('#')[0] + anchor);
callback && callback();
});
}
$.fn.scrollToAnchor = scrollToAnchor;
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function affix(options) {
var $root = this, $window = $(window), $scrollTarget, $scroll,
offsetBottom = 0, scrollTarget = window, scroll = window.document, disabled = false, isOverallScroller = true,
rootTop, rootLeft, rootHeight, scrollBottom, rootBottomTop,
hasInit = false, curState;
function setOptions(options) {
var _options = options || {};
_options.offsetBottom && (offsetBottom = _options.offsetBottom);
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
_options.scroll && (scroll = _options.scroll);
_options.disabled !== undefined && (disabled = _options.disabled);
$scrollTarget = $(scrollTarget);
isOverallScroller = window.isOverallScroller($scrollTarget[0]);
$scroll = $(scroll);
}
function preCalc() {
top();
rootHeight = $root.outerHeight();
rootTop = $root.offset().top + (isOverallScroller ? 0 : $scrollTarget.scrollTop());
rootLeft = $root.offset().left;
}
function calc(needPreCalc) {
needPreCalc && preCalc();
scrollBottom = $scroll.outerHeight() - offsetBottom - rootHeight;
rootBottomTop = scrollBottom - rootTop;
}
function top() {
if (curState !== 'top') {
$root.removeClass('fixed').css({
left: 0,
top: 0
});
curState = 'top';
}
}
function fixed() {
if (curState !== 'fixed') {
$root.addClass('fixed').css({
left: rootLeft + 'px',
top: 0
});
curState = 'fixed';
}
}
function bottom() {
if (curState !== 'bottom') {
$root.removeClass('fixed').css({
left: 0,
top: rootBottomTop + 'px'
});
curState = 'bottom';
}
}
function setState() {
var scrollTop = $scrollTarget.scrollTop();
if (scrollTop >= rootTop && scrollTop <= scrollBottom) {
fixed();
} else if (scrollTop < rootTop) {
top();
} else {
bottom();
}
}
function init() {
if(!hasInit) {
var interval, timeout;
calc(true); setState();
// run calc every 100 millisecond
interval = setInterval(function() {
calc();
}, 100);
timeout = setTimeout(function() {
clearInterval(interval);
}, 45000);
window.pageLoad.then(function() {
setTimeout(function() {
clearInterval(interval);
clearTimeout(timeout);
}, 3000);
});
$scrollTarget.on('scroll', function() {
disabled || setState();
});
$window.on('resize', function() {
disabled || (calc(true), setState());
});
hasInit = true;
}
}
setOptions(options);
if (!disabled) {
init();
}
$window.on('resize', window.throttle(function() {
init();
}, 200));
return {
setOptions: setOptions,
refresh: function() {
calc(true, { animation: false }); setState();
}
};
}
$.fn.affix = affix;
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function toc(options) {
var $root = this, $window = $(window), $scrollTarget, $scroller, $tocUl = $('<ul class="toc toc--ellipsis"></ul>'), $tocLi, $headings, $activeLast, $activeCur,
selectors = 'h1,h2,h3', container = 'body', scrollTarget = window, scroller = 'html, body', disabled = false,
headingsPos, scrolling = false, hasRendered = false, hasInit = false;
function setOptions(options) {
var _options = options || {};
_options.selectors && (selectors = _options.selectors);
_options.container && (container = _options.container);
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
_options.scroller && (scroller = _options.scroller);
_options.disabled !== undefined && (disabled = _options.disabled);
$headings = $(container).find(selectors).filter('[id]');
$scrollTarget = $(scrollTarget);
$scroller = $(scroller);
}
function calc() {
headingsPos = [];
$headings.each(function() {
headingsPos.push(Math.floor($(this).position().top));
});
}
function setState(element, disabled) {
var scrollTop = $scrollTarget.scrollTop(), i;
if (disabled || !headingsPos || headingsPos.length < 1) { return; }
if (element) {
$activeCur = element;
} else {
for (i = 0; i < headingsPos.length; i++) {
if (scrollTop >= headingsPos[i]) {
$activeCur = $tocLi.eq(i);
} else {
$activeCur || ($activeCur = $tocLi.eq(i));
break;
}
}
}
$activeLast && $activeLast.removeClass('active');
($activeLast = $activeCur).addClass('active');
}
function render() {
if(!hasRendered) {
$root.append($tocUl);
$headings.each(function() {
var $this = $(this);
$tocUl.append($('<li></li>').addClass('toc-' + $this.prop('tagName').toLowerCase())
.append($('<a></a>').text($this.text()).attr('href', '#' + $this.prop('id'))));
});
$tocLi = $tocUl.children('li');
$tocUl.on('click', 'a', function(e) {
e.preventDefault();
var $this = $(this);
scrolling = true;
setState($this.parent());
$scroller.scrollToAnchor($this.attr('href'), 400, function() {
scrolling = false;
});
});
}
hasRendered = true;
}
function init() {
var interval, timeout;
if(!hasInit) {
render(); calc(); setState(null, scrolling);
// run calc every 100 millisecond
interval = setInterval(function() {
calc();
}, 100);
timeout = setTimeout(function() {
clearInterval(interval);
}, 45000);
window.pageLoad.then(function() {
setTimeout(function() {
clearInterval(interval);
clearTimeout(timeout);
}, 3000);
});
$scrollTarget.on('scroll', function() {
disabled || setState(null, scrolling);
});
$window.on('resize', window.throttle(function() {
if (!disabled) {
render(); calc(); setState(null, scrolling);
}
}, 100));
}
hasInit = true;
}
setOptions(options);
if (!disabled) {
init();
}
$window.on('resize', window.throttle(function() {
init();
}, 200));
return {
setOptions: setOptions
};
}
$.fn.toc = toc;
});
})();
/*(function () {
})();*/
</script><script>
/* toc must before affix, since affix need to konw toc' height. */(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
var TOC_SELECTOR = window.TEXT_VARIABLES.site.toc.selectors;
window.Lazyload.js(SOURCES.jquery, function() {
var $window = $(window);
var $articleContent = $('.js-article-content');
var $tocRoot = $('.js-toc-root'), $col2 = $('.js-col-aside');
var toc;
var tocDisabled = false;
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
var hasToc = $articleContent.find(TOC_SELECTOR).length > 0;
function disabled() {
return $col2.css('display') === 'none' || !hasToc;
}
tocDisabled = disabled();
toc = $tocRoot.toc({
selectors: TOC_SELECTOR,
container: $articleContent,
scrollTarget: hasSidebar ? '.js-page-main' : null,
scroller: hasSidebar ? '.js-page-main' : null,
disabled: tocDisabled
});
$window.on('resize', window.throttle(function() {
tocDisabled = disabled();
toc && toc.setOptions({
disabled: tocDisabled
});
}, 100));
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
var $window = $(window), $pageFooter = $('.js-page-footer');
var $pageAside = $('.js-page-aside');
var affix;
var tocDisabled = false;
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
affix = $pageAside.affix({
offsetBottom: $pageFooter.outerHeight(),
scrollTarget: hasSidebar ? '.js-page-main' : null,
scroller: hasSidebar ? '.js-page-main' : null,
scroll: hasSidebar ? $('.js-page-main').children() : null,
disabled: tocDisabled
});
$window.on('resize', window.throttle(function() {
affix && affix.setOptions({
disabled: tocDisabled
});
}, 100));
window.pageAsideAffix = affix;
});
})();
</script><!---->
</div>
<script>(function () {
var $root = document.getElementsByClassName('root')[0];
if (window.hasEvent('touchstart')) {
$root.dataset.isTouch = true;
document.addEventListener('touchstart', function(){}, false);
}
})();
</script>
</body>
</html>