yannstatic/static/2019/12/25/illyse-openvpn.html

2811 lines
222 KiB
HTML
Raw 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>illyse-openvpn - YannStatic</title>
<meta name="description" content="illyse-openvpn">
<link rel="canonical" href="https://static.rnmkcy.eu/2019/12/25/illyse-openvpn.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;">illyse-openvpn</h1></header></div><meta itemprop="headline" content="illyse-openvpn"><div class="article__info clearfix"><ul class="left-col menu"><li>
<a class="button button--secondary button--pill button--sm"
href="/archive.html?tag=vpn">vpn</a>
</li></ul><ul class="right-col menu"><li>
<i class="far fa-calendar-alt"></i>&nbsp;<span title="Création" style="color:#FF00FF">25&nbsp;déc.&nbsp;&nbsp;2019</span>
<span title="Modification" style="color:#00FF7F">23&nbsp;nov.&nbsp;&nbsp;2018</span></li></ul></div><meta itemprop="datePublished" content="2018-11-23T00:00:00+01:00">
<meta itemprop="keywords" content="vpn"><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><h1 id="illyse-openvpn">illyse-openvpn</h1>
<h2 id="documentation-utilisateur-pour-le-vpn-illyse">Documentation utilisateur pour le VPN Illyse</h2>
<p><a href="https://doc.illyse.net/projects/publicdocs/wiki/Vpn_doc_user#Utiliser-simultanément-la-connexion-normale-et-le-VPN-sortie-par-défaut-via-le-VPN-et-faire-AP-WiFi">https://doc.illyse.net/projects/publicdocs/wiki/Vpn_doc_user#Utiliser-simultanément-la-connexion-normale-et-le-VPN-sortie-par-défaut-via-le-VPN-et-faire-AP-WiFi</a></p>
<p>Le VPN dIllyse utilise <strong>OpenVPN</strong>, qui a lavantage de fonctionner sur
à peu près nimporte quelle plate-forme (GNU/Linux, OS X, Windows,
Android, …)</p>
<p>Cette page sert de documentation utilisateur. Pour linstant, elle
contient principalement des exemples de fichier de configuration pour le
client openvpn.</p>
<p>Les fichiers de configuration donnés ici sont génériques, au sens où le
reste de la configuration se fait via linterface web abonné Illyse :
<a href="https://coin.illyse.org/">https://coin.illyse.org/</a> (adresses IP à utiliser sur le tunnel, etc).</p>
<h3 id="avant-de-commencer">Avant de commencer</h3>
<p>Se connecter au SI dIllyse avec le nom dutilisateur communiqué par
mail : <a href="https://coin.illyse.org/members/login/?next=/">COIN.</a> Si cest
votre première connexion, choisir un mot de passe pour COIN et bien le
retenir.</p>
<p>Aller dans la catégorie “Mes Abonnements”. Si rien napparaît alors que
vous avez souscrit au VPN, contacter <a href="mailto:adminsys@illyse.org">adminsys@illyse.org</a>.</p>
<p>A la ligne “VPN”, cliquer sur “*Configuration*”. Noter le nom
dutilisateur (le mieux est de le copier dans un fichier texte brut,
nous verrons pourquoi ensuite). Générer un mot de passe et le copier
dans le même fichier. Attention, si vous perdez votre mot de passe il
faudra en générer un nouveau.<br />
Si on installe le VPN sur une <a href="https://labriqueinter.net/">brique
internet</a> , noter aussi ladresse IPv4 et
ladresse IPv6 liées à votre VPN.</p>
<h2 id="note-importante-sur-la-sécurité">Note importante sur la sécurité</h2>
<p>Le VPN Illyse fournit une <strong>IPv4 publique</strong> et de lIPv6 (elle aussi
publique, évidemment). <strong>Aucun pare-feu (firewall) nest en place côté
Illyse</strong> : assurez-vous davoir un <strong>pare-feu (firewall)</strong> sur votre
machine lorsque vous utilisez le VPN.<br />
De plus il est possible que votre pare-feu considère la connexion VPN
comme faisant partie dun réseau “privé” et abaisse le niveau de
sécurité sur cette connexion.</p>
<p>Vous pourriez vous retrouver à exposer sur Internet, entre autres :</p>
<ul>
<li>un serveur SSH, avec des mots de passe faibles,</li>
<li>un serveur Web, avec une application en cours de développement,</li>
<li>un serveur mail mal configuré, susceptible de relayer du spam
(open-relay) et de provoquer rapidement linscription de votre
adresse IP dans des listes noires (RBL),</li>
<li>le protocole SMB sur les systèmes Microsoft Windows, qui permet
entre autres daccéder aux partages réseaux et aux imprimantes.</li>
</ul>
<p>Gardez à lesprit que votre adresse IPv4 publique sera lobjet de scans
intensifs depuis Internet, surtout si elle est utilisée pour la première
fois.</p>
<p>Illyse vous fournit un accès à Internet neutre, ce qui signifie entre
autres que lassociation ne se permet pas de décider à la place ses
abonnés de ce quil faut filtrer sur leur connexion.</p>
<p>Nhésitez pas à demander de laide, à poser des questions, dans
lassociation ou ailleurs, pour conserver la pleine maîtrise de votre
connexion :)</p>
<h2 id="paramètres-de-connexion-openvpn">Paramètres de connexion OpenVPN</h2>
<p>Si vous savez déjà utiliser OpenVPN, les informations les plus
importantes sont les suivantes :</p>
<ul>
<li><strong>Serveur :</strong> vpn.illyse.net</li>
<li><strong>Protocole :</strong> UDP recommandé, TCP possible</li>
<li><strong>Port :</strong> quelconque (1194 est le port standard OpenVPN, mais tous
les ports mènent au serveur VPN)</li>
<li><strong>Compression :</strong> non</li>
<li><strong>Fragmentation :</strong> 1300 octets</li>
<li><strong>TCP MSS fix :</strong> 1300 octets</li>
</ul>
<p>Notez donc que le serveur OpenVPN dIllyse écoute à la fois en UDP et en
TCP, et ce, sur nimporte quel port. Si vous êtes sur un réseau
complètement bloqué mais que UDP/53 ou TCP/443 passe, pas de problème,
le VPN passe !</p>
<p>Pour des raisons de performance, UDP est recommandé. Nutilisez le mode
TCP quen dernier recours. Référence :
<a href="http://sites.inka.de/bigred/devel/tcp-tcp.html">http://sites.inka.de/bigred/devel/tcp-tcp.html</a></p>
<h1 id="exemples-de-configuration">Exemples de configuration.</h1>
<p>Ces exemples de fichiers de configuration sont là pour vous aider à vous
connecter au VPN.</p>
<h2 id="gnulinux-debian-wheezy">GNU/Linux (Debian Wheezy)</h2>
<h3 id="pour-les-débutants">Pour les débutants</h3>
<p>Installer OpenVPN : ouvrir un terminal et taper “sudo aptitude install
openvpn”. Se connecter en root dans le terminal (“sudo su”) et se placer
dans le répertoire /etc/openvpn/ (“cd /etc/openvpn/”). Créer le fichier
texte nommé illyse.conf (nano illyse.conf) et copier dedans la
configuration ci-dessous. Créer le fichier texte nommé credentials et y
insérer le nom dutilisateur et le mot de passe stockés précédemment
(une ligne chacun, voir modèle ci-dessous).</p>
<p>Lancer le VPN avec la commande “service openvpn start illyse” (besoin
dêtre root). Ça devrait fonctionner ! Si ce nest pas le cas, vérifier
les étapes précédentes, et la connexion Internet. Si ça ne fonctionne
toujours pas, écrire un gentil mail à <a href="mailto:adminsys@illyse.org">adminsys@illyse.org</a> en joignant
le rapport derreur situé ici : /var/log/openvpn-illyse.log. Pour
stopper le VPN, taper la commande “service openvpn stop illyse”.</p>
<h3 id="fichier-de-configuration-openvpn">Fichier de configuration OpenVPN</h3>
<p>La configuration est commentée, nhésitez pas à changer des paramètres.
Avec les paramètres ci-dessous, une IPv4 et une IPv6 seront attribués,
et tout le trafic passera par le VPN.</p>
<p>/etc/openvpn/illyse.conf</p>
<p># Cest nous qui prenons linitiative de nous connecter au serveur.<br />
client<br />
# On route de lIP, on ne fait pas de lethernet.<br />
dev tun0<br />
# si on ne reçoit pas dIP pour tun0:<br />
# - soit on configure linterface avec des ip privées bidon<br />
#ifconfig 10.255.255.1 10.255.255.2<br />
# - soit on utilise un script pour faire “ifconfig tun0 up”<br />
#script-security 2<br />
#up up.sh<br />
# Il est préférable dutiliser udp, le résultat fonctionne mieux. Il
est<br />
# cependant notable que les restrictions daccès Internet laissent
souvent<br />
# plus facilement passer tcp. Essayez donc udp, et seulement sil ne
fonctionne<br />
# pas, essayez tcp.<br />
# Transport sur udp v4. En v6, la redirection de passerelle par défaut
fonctionne mal (openvpn ne crée pas léquivalent de la route /32 IPv4
vers le serveur vpn via la passerelle sous-jacente)<br />
# Si on ne prévoit pas dutiliser la directive “redirect-gateway def1”,
alors on peut choisir “proto udp6” pour monter le tunnel en IPv6.<br />
#proto udp6<br />
proto udp<br />
#proto tcp<br />
# Certains réseaux ont en fait une MTU bien inférieure à 1450. Dire aux
connexions<br />
# TCP dêtre très conservatives, pour que ça marche plus ou moins
partout.<br />
mssfix 1300<br />
# En UDP, on peut sassurer que ça passe de toutes façons en
fragmentant au besoin<br />
# quand ça dépasse.<br />
fragment 1300<br />
# Idéalement, ça devrait être détecté tout seul, mais cest loin de
toujours fonctionner…<br />
#mtu-disc yes<br />
# En udp, Prévenir le serveur quand on termine, permet de relancer<br />
# immédiatement sans attendre que le serveur se rende compte de la<br />
# déconnexion par timeout.<br />
explicit-exit-notify<br />
# Ladresse du serveur.<br />
remote vpn.illyse.net 1194<br />
# Éventuellement, on peut avoir besoin de passer par un proxy http,
décommenter cette ligne en mettant ladresse et le port du proxy.<br />
#http-proxy 192.0.2.1 8080<br />
# Attendre un peu avant dajouter les routes.<br />
route-delay 2<br />
# Ne pas utiliser un port local statique, on est client de toutes
façons.<br />
nobind<br />
# Garder la clé en mémoire, pour ne pas avoir besoin de la relire lors
dun<br />
# redémarrage.<br />
persist-key<br />
# Ne pas tuer linterface du tunnel lors dun redémarrage.<br />
#persist-tun<br />
# Décommenter cette ligne pour faire passer tout le trafic via le VPN:<br />
redirect-gateway def1<br />
# On peut aussi vouloir plutôt router seulement quelques destinations,
par<br />
# exemple ici tout Gitoyen:<br />
#route 80.67.160.0 255.255.224.0<br />
# Activer IPv6 dans le tunnel<br />
tun-ipv6<br />
# et faire passer tout le trafic IPv6 via le VPN:<br />
route-ipv6 ::/1<br />
route-ipv6 8000::/1<br />
# Envoyer un login et un mot de passe. Pour éviter de taper à la main
login<br />
# et mot de passe, vous pouvez ajouter à droite de “auth-user-pass” le
nom dun<br />
# fichier contenant ces deux informations, une par ligne.<br />
auth-user-pass credentials<br />
# Retenter le lauthentification même si le serveur la refuse (utile
pour<br />
# éviter de faire mourir le client si le serveur LDAP ne répond pas)<br />
auth-retry nointeract<br />
# Un minimum de debug, cest toujours bien.<br />
verb 3<br />
log-append /var/log/openvpn-illyse.log<br />
# Certificat permettant de vérifier que cest bien à Illyse que<br />
# lon se connecte et donc à qui on donne notre mot de passe.<br />
remote-cert-tls server<br />
&lt;ca&gt;</p>
<p>BEGIN CERTIFICATE—<br />
MIIG2TCCBMGgAwIBAgIJAPAWK4ceEBXzMA0GCSqGSIb3DQEBBQUAMIGjMQswCQYD<br />
VQQGEwJGUjEMMAoGA1UECBMDUkhBMRUwEwYDVQQHEwxWaWxsZXVyYmFubmUxDzAN<br />
BgNVBAoTBklMTFlTRTEQMA4GA1UECxMHb3BlbnZwbjEaMBgGA1UEAxMRaWxseXNl<br />
LW9wZW52cG4tY2ExDzANBgNVBCkTBklMTFlTRTEfMB0GCSqGSIb3DQEJARYQYWJ1<br />
c2VAaWxseXNlLm9yZzAeFw0xNDAzMTgyMTMyMjNaFw0yNDAzMTUyMTMyMjNaMIGj<br />
MQswCQYDVQQGEwJGUjEMMAoGA1UECBMDUkhBMRUwEwYDVQQHEwxWaWxsZXVyYmFu<br />
bmUxDzANBgNVBAoTBklMTFlTRTEQMA4GA1UECxMHb3BlbnZwbjEaMBgGA1UEAxMR<br />
aWxseXNlLW9wZW52cG4tY2ExDzANBgNVBCkTBklMTFlTRTEfMB0GCSqGSIb3DQEJ<br />
ARYQYWJ1c2VAaWxseXNlLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC<br />
ggIBAKl/s6IoAsJTxw82xps5PHPTMjKhONFNk4gJMdSngbhGMcRM5ebwD9Dhfava<br />
w9NjWiwNhikhnRWW3HGrv+BE7cqga16ryuLCievG1nfqZMpa3EnfWwwmHClMV9Zf<br />
OPb/AD2V3t2MAvZ1ZcvyTe/p/3eHovHhEHJ2qXtd0iI9u8b7xcEm9vXIw7kYN2dQ<br />
xIe9Wd85tja2IBtf67oBS8JZxSkIcEY7KAXsFUtFyGn6fbPGj8UGM+roiYqzEYa/<br />
BNvc2eEfhhpHSoN5vRKu0LrVUA3uA41dOKcxW15af4Xy058l0aUWeSK64jK/cL24<br />
fmBZoQfdS9U5P5wnm4tpRR7oesdrohhbVWn4JjRyF31HM1FtAoT6oTqhhlrImpGw<br />
j7nAGlItT04C73wgiSajFJryo24XuedzjFxm3BetAcSUyE5e3BSqTUbEtWdTdiw1<br />
l3/WQyyBrn98SChBExmpklecI5eFp/DoLBqwW/U/vseD7zMfF7OHnHtbsbniUujN<br />
WjNGiWnVJ636nTfPIDsngGTACWh5ZwxX0fGW2+RqS2NN9R1dGWdW34lgfwx04Wzc<br />
l0NZ++itmJq5iJUw9Kj9mmQZn96V8b6hDnhcJfkvUlgxhHcZ5isfOwQq6UcP3mZP<br />
zOCWuCwIKNPMLcJmC684mkJJrJuCc6N9pNm7jjmdPkW/0j2VAgMBAAGjggEMMIIB<br />
CDAdBgNVHQ4EFgQUXUSESsSBdTGjlbvo+Sbsiwo+E/4wgdgGA1UdIwSB0DCBzYAU<br />
XUSESsSBdTGjlbvo+Sbsiwo+E/6hgamkgaYwgaMxCzAJBgNVBAYTAkZSMQwwCgYD<br />
VQQIEwNSSEExFTATBgNVBAcTDFZpbGxldXJiYW5uZTEPMA0GA1UEChMGSUxMWVNF<br />
MRAwDgYDVQQLEwdvcGVudnBuMRowGAYDVQQDExFpbGx5c2Utb3BlbnZwbi1jYTEP<br />
MA0GA1UEKRMGSUxMWVNFMR8wHQYJKoZIhvcNAQkBFhBhYnVzZUBpbGx5c2Uub3Jn<br />
ggkA8BYrhx4QFfMwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAgEATAlP<br />
EQXjzQ10xkQdUNXjy+s87DWcbpu3n4Wlc4E828Ek6D1LhbPeVL7wTyhHj+Txxy8o<br />
4sCCL+oH/HgnMEy7VHs0HXpD3F9iPD8U3QiL1sfO+0IKOhBOKAsjmpuH+oCsXpZ0<br />
J/GnebPQ6S+wBFCZH3uU5jIeB4WCFpzn2WQVIXh+lzKKWLN3GxfxdWkIyl4Fluj4<br />
6k0Lj35EtE74wZTWbCkum7rNOp9gnGtrcyAupwj2MTeVcLzigYLth/G6AA3a7VeE<br />
hlvJqV7URhiwXL8lQjaMoDFYiD8zhBn44tLwKMiTvyHfNs0+1mcteoDwI20SKo3F<br />
VUnyCqc9k9Dq0YfE4RqhjmsMcV6HydaznCclnIrugPdFAQzGbk7bNZJ3yv0ATj9Z<br />
wcfHxIUEuPl392OvJDm/JEbegonQ4yyv2B8OAacZ4HPm/6FeYS/jyOe66BUku0rd<br />
LSVaB9OD7iVWkW5eo6ng3XA390HIUUtf/0IdtiCoMsjuZbVagfiaUu0kUJpR6d2k<br />
r5czdLFhRu8uw0sWn1rMQXlUAqH0WAfoq8XinaHesWs5MEnvevjoUTkNhFnqe1Ra<br />
rkwU9mzr1/N6GfpPalbveD0duTGAkJN5mwLZi+HZ4ctLgO1ShYFU/NbC7jNU3YCU<br />
sjvtdavgLFaMPLPrI2DAcjpVMUuL1VgdqUcQkhc=<br />
END CERTIFICATE—</p>
<p>&lt;/ca&gt;</p>
<p>/etc/openvpn/credentials<br />
(Seulement si vous voulez stocker votre mot de passe. En clair. Oui,
cest moche.)</p>
<p>Spécifier login et mot de passe sur deux lignes différences.</p>
<p>jkleboulet-vpn1</p>
<p>omgsuchsecured123</p>
<h3 id="mise-à-jour-automatique-de-resolvconf">Mise à jour automatique de resolv.conf</h3>
<p>Pour que resolv.conf soit mis à jour par openvpn avec les IP des
resolvers DNS Illyse poussées par le serveur VPN.</p>
<p>&lt;mit-mit&gt; Bon, ça marche, faut ajouter à la config :
&lt;mit-mit&gt; script-security 2
&lt;mit-mit&gt; up /etc/openvpn/update-resolv-conf
&lt;mit-mit&gt; down /etc/openvpn/update-resolv-conf
&lt;mit-mit&gt; et avoir resolvconf dinstallé.
&lt;mit-mit&gt; (la première ligne étant lautorisation de lancement de
scripts externes)</p>
<h2 id="gnulinux-network-manager">GNU/Linux (Network Manager)</h2>
<p>Il est possible de configurer graphiquement le VPN via Network Manager.<br />
(Jutilise la version KDE, des détails peuvent varier si vous utilisez
la version gtk)</p>
<p>Téléchargez le fichier
<a href="https://doc.illyse.net/attachments/download/437/vpn-illyse.crt">vpn-illyse.crt</a>.</p>
<p>Installez le backend openvpn pour Network Manager, puis créez une
nouvelle connexion de type openvpn.<br />
Complétez comme suit, indiquez le chemin du fichier crt, votre login et
votre mot de passe VPN:<br />
<img src="Pictures/100002010000024300000239D2F37C9538ABDD2F.png" alt="" width="578" height="569" /><br />
Cliquez sur «Avancé», mettez 1300 dans «Taille du fragment UDP» et
cochez «Restreindre la taille maximale du segment TCP (MSS)»<br />
<img src="Pictures/1000020100000252000002098095FBA2C9C3828C.png" alt="" width="593" height="521" /></p>
<h2 id="windows">Windows</h2>
<p>Installez OpenVPN, par exemple en suivant la documentation présente
ici: <a href="http://www.rezine.org/documentation/tunnels_chiffres/#index4h1">http://www.rezine.org/documentation/tunnels_chiffres/#index4h1</a></p>
<p>Créez ensuite le fichier suivant.<br />
Faites attention à lextension des fichiers: parfois Windows ajoute une
extension .txt aux fichiers sans le dire.</p>
<p>C:\Program Files\OpenVPN\config\illyse\illyse.ovpn</p>
<p># Cest nous qui prenons linitiative de nous connecter au serveur.<br />
client<br />
# On route de lIP, on ne fait pas de lethernet.<br />
dev tun0<br />
# si on ne reçoit pas dIP pour tun0:<br />
# - soit on configure linterface avec des ip privées bidon<br />
#ifconfig 10.255.255.1 10.255.255.2<br />
# - soit on utilise un script pour faire “ifconfig tun0 up”<br />
#script-security 2<br />
#up up.sh<br />
# Il est préférable dutiliser udp, le résultat fonctionne mieux. Il
est<br />
# cependant notable que les restrictions daccès Internet laissent
souvent<br />
# plus facilement passer tcp. Essayez donc udp, et seulement sil ne
fonctionne<br />
# pas, essayez tcp.<br />
#proto udp6<br />
proto udp<br />
#proto tcp<br />
# Certains réseaux ont en fait une MTU bien inférieure à 1450. Dire aux
connexions<br />
# TCP dêtre très conservatives, pour que ça marche plus ou moins
partout.<br />
mssfix 1300<br />
# En UDP, on peut sassurer que ça passe de toutes façons en
fragmentant au besoin<br />
# quand ça dépasse.<br />
fragment 1300<br />
# Idéalement, ça devrait être détecté tout seul, mais cest loin de
toujours fonctionner…<br />
#mtu-disc yes<br />
#mtu-test<br />
#link-mtu 1300<br />
#tun-mtu 1300<br />
# En udp, Prévenir le serveur quand on termine, permet de relancer<br />
# immédiatement sans attendre que le serveur se rende compte de la<br />
# déconnexion par timeout.<br />
explicit-exit-notify<br />
# Ladresse du serveur.<br />
remote vpn.illyse.net 1194<br />
# Éventuellement, on peut avoir besoin de passer par un proxy http,
décommenter cette ligne en mettant ladresse et le port du proxy.<br />
#http-proxy 192.0.2.1 8080<br />
# Pour windows: utiliser route.exe.<br />
route-method exe<br />
# Attendre un peu avant dajouter les routes.<br />
route-delay 2<br />
# Ne pas utiliser un port local statique, on est client de toutes
façons.<br />
nobind<br />
# Garder la clé en mémoire, pour ne pas avoir besoin de la relire lors
dun<br />
# redémarrage.<br />
persist-key<br />
# Ne pas tuer linterface du tunnel lors dun redémarrage.<br />
#persist-tun<br />
#ip-win32 ipapi<br />
# Décommenter cette ligne pour faire passer tout le trafic via le VPN:<br />
redirect-gateway def1<br />
# On peut aussi vouloir plutôt router seulement quelques destinations,
par<br />
# exemple ici tout Gitoyen:<br />
#route 80.67.160.0 255.255.224.0<br />
# Activer IPv6 dans le VPN<br />
tun-ipv6<br />
# Faire passer tout le trafic IPv6 via le VPN:<br />
route-ipv6 ::/1<br />
route-ipv6 8000::/1<br />
# Envoyer un login et un mot de passe. Pour éviter de taper à la main
login<br />
# et mot de passe, vous pouvez ajouter à droite de “auth-user-pass” le
nom dun<br />
# fichier contenant ces deux informations, une par ligne.<br />
auth-user-pass credentials<br />
# Un minimum de debug, cest toujours bien.<br />
verb 3<br />
#log-append /var/log/openvpn-illyse.log<br />
# Certificat permettant de vérifier que cest bien à Illyse que<br />
# lon se connecte et donc à qui on donne notre mot de passe.</p>
<p>remote-cert-tls server</p>
<p>&lt;ca&gt;</p>
<p>BEGIN CERTIFICATE—<br />
MIIG2TCCBMGgAwIBAgIJAPAWK4ceEBXzMA0GCSqGSIb3DQEBBQUAMIGjMQswCQYD<br />
VQQGEwJGUjEMMAoGA1UECBMDUkhBMRUwEwYDVQQHEwxWaWxsZXVyYmFubmUxDzAN<br />
BgNVBAoTBklMTFlTRTEQMA4GA1UECxMHb3BlbnZwbjEaMBgGA1UEAxMRaWxseXNl<br />
LW9wZW52cG4tY2ExDzANBgNVBCkTBklMTFlTRTEfMB0GCSqGSIb3DQEJARYQYWJ1<br />
c2VAaWxseXNlLm9yZzAeFw0xNDAzMTgyMTMyMjNaFw0yNDAzMTUyMTMyMjNaMIGj<br />
MQswCQYDVQQGEwJGUjEMMAoGA1UECBMDUkhBMRUwEwYDVQQHEwxWaWxsZXVyYmFu<br />
bmUxDzANBgNVBAoTBklMTFlTRTEQMA4GA1UECxMHb3BlbnZwbjEaMBgGA1UEAxMR<br />
aWxseXNlLW9wZW52cG4tY2ExDzANBgNVBCkTBklMTFlTRTEfMB0GCSqGSIb3DQEJ<br />
ARYQYWJ1c2VAaWxseXNlLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC<br />
ggIBAKl/s6IoAsJTxw82xps5PHPTMjKhONFNk4gJMdSngbhGMcRM5ebwD9Dhfava<br />
w9NjWiwNhikhnRWW3HGrv+BE7cqga16ryuLCievG1nfqZMpa3EnfWwwmHClMV9Zf<br />
OPb/AD2V3t2MAvZ1ZcvyTe/p/3eHovHhEHJ2qXtd0iI9u8b7xcEm9vXIw7kYN2dQ<br />
xIe9Wd85tja2IBtf67oBS8JZxSkIcEY7KAXsFUtFyGn6fbPGj8UGM+roiYqzEYa/<br />
BNvc2eEfhhpHSoN5vRKu0LrVUA3uA41dOKcxW15af4Xy058l0aUWeSK64jK/cL24<br />
fmBZoQfdS9U5P5wnm4tpRR7oesdrohhbVWn4JjRyF31HM1FtAoT6oTqhhlrImpGw<br />
j7nAGlItT04C73wgiSajFJryo24XuedzjFxm3BetAcSUyE5e3BSqTUbEtWdTdiw1<br />
l3/WQyyBrn98SChBExmpklecI5eFp/DoLBqwW/U/vseD7zMfF7OHnHtbsbniUujN<br />
WjNGiWnVJ636nTfPIDsngGTACWh5ZwxX0fGW2+RqS2NN9R1dGWdW34lgfwx04Wzc<br />
l0NZ++itmJq5iJUw9Kj9mmQZn96V8b6hDnhcJfkvUlgxhHcZ5isfOwQq6UcP3mZP<br />
zOCWuCwIKNPMLcJmC684mkJJrJuCc6N9pNm7jjmdPkW/0j2VAgMBAAGjggEMMIIB<br />
CDAdBgNVHQ4EFgQUXUSESsSBdTGjlbvo+Sbsiwo+E/4wgdgGA1UdIwSB0DCBzYAU<br />
XUSESsSBdTGjlbvo+Sbsiwo+E/6hgamkgaYwgaMxCzAJBgNVBAYTAkZSMQwwCgYD<br />
VQQIEwNSSEExFTATBgNVBAcTDFZpbGxldXJiYW5uZTEPMA0GA1UEChMGSUxMWVNF<br />
MRAwDgYDVQQLEwdvcGVudnBuMRowGAYDVQQDExFpbGx5c2Utb3BlbnZwbi1jYTEP<br />
MA0GA1UEKRMGSUxMWVNFMR8wHQYJKoZIhvcNAQkBFhBhYnVzZUBpbGx5c2Uub3Jn<br />
ggkA8BYrhx4QFfMwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAgEATAlP<br />
EQXjzQ10xkQdUNXjy+s87DWcbpu3n4Wlc4E828Ek6D1LhbPeVL7wTyhHj+Txxy8o<br />
4sCCL+oH/HgnMEy7VHs0HXpD3F9iPD8U3QiL1sfO+0IKOhBOKAsjmpuH+oCsXpZ0<br />
J/GnebPQ6S+wBFCZH3uU5jIeB4WCFpzn2WQVIXh+lzKKWLN3GxfxdWkIyl4Fluj4<br />
6k0Lj35EtE74wZTWbCkum7rNOp9gnGtrcyAupwj2MTeVcLzigYLth/G6AA3a7VeE<br />
hlvJqV7URhiwXL8lQjaMoDFYiD8zhBn44tLwKMiTvyHfNs0+1mcteoDwI20SKo3F<br />
VUnyCqc9k9Dq0YfE4RqhjmsMcV6HydaznCclnIrugPdFAQzGbk7bNZJ3yv0ATj9Z<br />
wcfHxIUEuPl392OvJDm/JEbegonQ4yyv2B8OAacZ4HPm/6FeYS/jyOe66BUku0rd<br />
LSVaB9OD7iVWkW5eo6ng3XA390HIUUtf/0IdtiCoMsjuZbVagfiaUu0kUJpR6d2k<br />
r5czdLFhRu8uw0sWn1rMQXlUAqH0WAfoq8XinaHesWs5MEnvevjoUTkNhFnqe1Ra<br />
rkwU9mzr1/N6GfpPalbveD0duTGAkJN5mwLZi+HZ4ctLgO1ShYFU/NbC7jNU3YCU<br />
sjvtdavgLFaMPLPrI2DAcjpVMUuL1VgdqUcQkhc=<br />
END CERTIFICATE—</p>
<p>&lt;/ca&gt;</p>
<p>Il est également possible de créer un fichier contenant vos logins et
mots de passe pour éviter de les taper à chaque connexion. Par exemple:</p>
<p>C:\Program Files\OpenVPN\config\illyse\credentials</p>
<p>jkleboulet-vpn1</p>
<p>omgsuchsecured123</p>
<p>Si vous ne voulez pas utiliser un tel fichier, commentez la ligne
«auth-user-pass credentials» dans la configuration.</p>
<h2 id="mac-os-x">Mac OS X</h2>
<p>Installer le client OpenVPN Tunnelblick :
<a href="https://code.google.com/p/tunnelblick/">https://code.google.com/p/tunnelblick/</a></p>
<p>Créer un fichier illyse.ovpn avec la configuration voulue. Celle
indiquée ci-dessous fonctionne sans modification necessaire.<br />
Double-cliquer sur le fichier afin que TunnelBlick import la
configuration.<br />
A la première connexion, il va demander un couple login/password quil
sera possible de stocker dans le trousseau.</p>
<p>Paramètres modifiés par rapport à la configuration pour Linux :</p>
<ul>
<li>log-append : Ce paramètre nest pas accepté. Mais tunnelblick log
déjà en interne.</li>
<li>auth-user-pass : On ne précise pas de fichier de credential, cest
géré par Tunnelblick et Keychains au moment de la connexion</li>
<li>Les commentaires ont été retirés car le fichier est tronqué au
moment de limport sil est trop long (ce qui était le cas)</li>
</ul>
<p>illyse.ovpn</p>
<p>client<br />
dev tun0<br />
proto udp<br />
mssfix 1300<br />
fragment 1300<br />
explicit-exit-notify<br />
remote vpn.illyse.net 1194<br />
#http-proxy 192.0.2.1 8080<br />
route-delay 2<br />
nobind<br />
persist-key<br />
persist-tun<br />
redirect-gateway def1<br />
#route 80.67.160.0 255.255.224.0<br />
tun-ipv6<br />
route-ipv6 ::/1<br />
route-ipv6 8000::/1<br />
auth-user-pass<br />
verb 3<br />
remote-cert-tls server</p>
<p>&lt;ca&gt;</p>
<p>BEGIN CERTIFICATE—<br />
MIIG2TCCBMGgAwIBAgIJAPAWK4ceEBXzMA0GCSqGSIb3DQEBBQUAMIGjMQswCQYD<br />
VQQGEwJGUjEMMAoGA1UECBMDUkhBMRUwEwYDVQQHEwxWaWxsZXVyYmFubmUxDzAN<br />
BgNVBAoTBklMTFlTRTEQMA4GA1UECxMHb3BlbnZwbjEaMBgGA1UEAxMRaWxseXNl<br />
LW9wZW52cG4tY2ExDzANBgNVBCkTBklMTFlTRTEfMB0GCSqGSIb3DQEJARYQYWJ1<br />
c2VAaWxseXNlLm9yZzAeFw0xNDAzMTgyMTMyMjNaFw0yNDAzMTUyMTMyMjNaMIGj<br />
MQswCQYDVQQGEwJGUjEMMAoGA1UECBMDUkhBMRUwEwYDVQQHEwxWaWxsZXVyYmFu<br />
bmUxDzANBgNVBAoTBklMTFlTRTEQMA4GA1UECxMHb3BlbnZwbjEaMBgGA1UEAxMR<br />
aWxseXNlLW9wZW52cG4tY2ExDzANBgNVBCkTBklMTFlTRTEfMB0GCSqGSIb3DQEJ<br />
ARYQYWJ1c2VAaWxseXNlLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC<br />
ggIBAKl/s6IoAsJTxw82xps5PHPTMjKhONFNk4gJMdSngbhGMcRM5ebwD9Dhfava<br />
w9NjWiwNhikhnRWW3HGrv+BE7cqga16ryuLCievG1nfqZMpa3EnfWwwmHClMV9Zf<br />
OPb/AD2V3t2MAvZ1ZcvyTe/p/3eHovHhEHJ2qXtd0iI9u8b7xcEm9vXIw7kYN2dQ<br />
xIe9Wd85tja2IBtf67oBS8JZxSkIcEY7KAXsFUtFyGn6fbPGj8UGM+roiYqzEYa/<br />
BNvc2eEfhhpHSoN5vRKu0LrVUA3uA41dOKcxW15af4Xy058l0aUWeSK64jK/cL24<br />
fmBZoQfdS9U5P5wnm4tpRR7oesdrohhbVWn4JjRyF31HM1FtAoT6oTqhhlrImpGw<br />
j7nAGlItT04C73wgiSajFJryo24XuedzjFxm3BetAcSUyE5e3BSqTUbEtWdTdiw1<br />
l3/WQyyBrn98SChBExmpklecI5eFp/DoLBqwW/U/vseD7zMfF7OHnHtbsbniUujN<br />
WjNGiWnVJ636nTfPIDsngGTACWh5ZwxX0fGW2+RqS2NN9R1dGWdW34lgfwx04Wzc<br />
l0NZ++itmJq5iJUw9Kj9mmQZn96V8b6hDnhcJfkvUlgxhHcZ5isfOwQq6UcP3mZP<br />
zOCWuCwIKNPMLcJmC684mkJJrJuCc6N9pNm7jjmdPkW/0j2VAgMBAAGjggEMMIIB<br />
CDAdBgNVHQ4EFgQUXUSESsSBdTGjlbvo+Sbsiwo+E/4wgdgGA1UdIwSB0DCBzYAU<br />
XUSESsSBdTGjlbvo+Sbsiwo+E/6hgamkgaYwgaMxCzAJBgNVBAYTAkZSMQwwCgYD<br />
VQQIEwNSSEExFTATBgNVBAcTDFZpbGxldXJiYW5uZTEPMA0GA1UEChMGSUxMWVNF<br />
MRAwDgYDVQQLEwdvcGVudnBuMRowGAYDVQQDExFpbGx5c2Utb3BlbnZwbi1jYTEP<br />
MA0GA1UEKRMGSUxMWVNFMR8wHQYJKoZIhvcNAQkBFhBhYnVzZUBpbGx5c2Uub3Jn<br />
ggkA8BYrhx4QFfMwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAgEATAlP<br />
EQXjzQ10xkQdUNXjy+s87DWcbpu3n4Wlc4E828Ek6D1LhbPeVL7wTyhHj+Txxy8o<br />
4sCCL+oH/HgnMEy7VHs0HXpD3F9iPD8U3QiL1sfO+0IKOhBOKAsjmpuH+oCsXpZ0<br />
J/GnebPQ6S+wBFCZH3uU5jIeB4WCFpzn2WQVIXh+lzKKWLN3GxfxdWkIyl4Fluj4<br />
6k0Lj35EtE74wZTWbCkum7rNOp9gnGtrcyAupwj2MTeVcLzigYLth/G6AA3a7VeE<br />
hlvJqV7URhiwXL8lQjaMoDFYiD8zhBn44tLwKMiTvyHfNs0+1mcteoDwI20SKo3F<br />
VUnyCqc9k9Dq0YfE4RqhjmsMcV6HydaznCclnIrugPdFAQzGbk7bNZJ3yv0ATj9Z<br />
wcfHxIUEuPl392OvJDm/JEbegonQ4yyv2B8OAacZ4HPm/6FeYS/jyOe66BUku0rd<br />
LSVaB9OD7iVWkW5eo6ng3XA390HIUUtf/0IdtiCoMsjuZbVagfiaUu0kUJpR6d2k<br />
r5czdLFhRu8uw0sWn1rMQXlUAqH0WAfoq8XinaHesWs5MEnvevjoUTkNhFnqe1Ra<br />
rkwU9mzr1/N6GfpPalbveD0duTGAkJN5mwLZi+HZ4ctLgO1ShYFU/NbC7jNU3YCU<br />
sjvtdavgLFaMPLPrI2DAcjpVMUuL1VgdqUcQkhc=<br />
END CERTIFICATE—</p>
<p>&lt;/ca&gt;</p>
<h2 id="android">Android</h2>
<p>Configuration OpenVPN pour Android (testé sous Android 4.4.4 et OpenVPN
for Android v0.6.17)<br />
Ci-après un fichier de configuration qui devrait fonctionner avec
lapplication Android OpenVPN for Android,<br />
Disponible sur F-Droid :
<a href="https://f-droid.org/repository/browse/?fdfilter=openvpn&amp;fdid=de.blinkt.openvpn">https://f-droid.org/repository/browse/?fdfilter=openvpn&amp;fdid=de.blinkt.openvpn</a><br />
Ou au pire sur le PlayStore :
<a href="https://play.google.com/store/apps/details?id=de.blinkt.openvpn">https://play.google.com/store/apps/details?id=de.blinkt.openvpn</a><br />
Posez le fichier de configuration, renommé en VPN-Illyse.conf par
exemple, sur lappareil.<br />
Une fois lapplication installée et démarrée, cliquez sur le dossier en
bas à droite et chezchez le fichier de configuration.<br />
Il suffit de renseigner les identifiants.</p>
<p>#<br />
# Fichier de configuration VPN Illyse pour Android<br />
# 2014-10-14<br />
#<br />
# Enables connection to GUI<br />
management /data/data/de.blinkt.openvpn/cache/mgmtsocket unix<br />
management-client<br />
management-query-passwords<br />
management-hold<br />
setenv IV_GUI_VER “de.blinkt.openvpn 0.6.17”<br />
machine-readable-output<br />
client<br />
verb 4<br />
connect-retry-max 5<br />
connect-retry 5<br />
resolv-retry 60<br />
dev tun<br />
remote vpn.illyse.net 1194 udp<br />
auth-user-pass<br />
route-ipv6 ::/0<br />
route 0.0.0.0 0.0.0.0 vpn_gateway<br />
remote-cert-tls server<br />
persist-tun<br />
# persist-tun also enables pre resolving to avoid DNS resolve problem<br />
preresolve<br />
# Use system proxy setting<br />
management-query-proxy<br />
# Custom configuration options<br />
# You are on your on own here<br />
mssfix 1300<br />
fragment 1300</p>
<p>&lt;ca&gt;</p>
<p>BEGIN CERTIFICATE—<br />
MIIG2TCCBMGgAwIBAgIJAPAWK4ceEBXzMA0GCSqGSIb3DQEBBQUAMIGjMQswCQYD<br />
VQQGEwJGUjEMMAoGA1UECBMDUkhBMRUwEwYDVQQHEwxWaWxsZXVyYmFubmUxDzAN<br />
BgNVBAoTBklMTFlTRTEQMA4GA1UECxMHb3BlbnZwbjEaMBgGA1UEAxMRaWxseXNl<br />
LW9wZW52cG4tY2ExDzANBgNVBCkTBklMTFlTRTEfMB0GCSqGSIb3DQEJARYQYWJ1<br />
c2VAaWxseXNlLm9yZzAeFw0xNDAzMTgyMTMyMjNaFw0yNDAzMTUyMTMyMjNaMIGj<br />
MQswCQYDVQQGEwJGUjEMMAoGA1UECBMDUkhBMRUwEwYDVQQHEwxWaWxsZXVyYmFu<br />
bmUxDzANBgNVBAoTBklMTFlTRTEQMA4GA1UECxMHb3BlbnZwbjEaMBgGA1UEAxMR<br />
aWxseXNlLW9wZW52cG4tY2ExDzANBgNVBCkTBklMTFlTRTEfMB0GCSqGSIb3DQEJ<br />
ARYQYWJ1c2VAaWxseXNlLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC<br />
ggIBAKl/s6IoAsJTxw82xps5PHPTMjKhONFNk4gJMdSngbhGMcRM5ebwD9Dhfava<br />
w9NjWiwNhikhnRWW3HGrv+BE7cqga16ryuLCievG1nfqZMpa3EnfWwwmHClMV9Zf<br />
OPb/AD2V3t2MAvZ1ZcvyTe/p/3eHovHhEHJ2qXtd0iI9u8b7xcEm9vXIw7kYN2dQ<br />
xIe9Wd85tja2IBtf67oBS8JZxSkIcEY7KAXsFUtFyGn6fbPGj8UGM+roiYqzEYa/<br />
BNvc2eEfhhpHSoN5vRKu0LrVUA3uA41dOKcxW15af4Xy058l0aUWeSK64jK/cL24<br />
fmBZoQfdS9U5P5wnm4tpRR7oesdrohhbVWn4JjRyF31HM1FtAoT6oTqhhlrImpGw<br />
j7nAGlItT04C73wgiSajFJryo24XuedzjFxm3BetAcSUyE5e3BSqTUbEtWdTdiw1<br />
l3/WQyyBrn98SChBExmpklecI5eFp/DoLBqwW/U/vseD7zMfF7OHnHtbsbniUujN<br />
WjNGiWnVJ636nTfPIDsngGTACWh5ZwxX0fGW2+RqS2NN9R1dGWdW34lgfwx04Wzc<br />
l0NZ++itmJq5iJUw9Kj9mmQZn96V8b6hDnhcJfkvUlgxhHcZ5isfOwQq6UcP3mZP<br />
zOCWuCwIKNPMLcJmC684mkJJrJuCc6N9pNm7jjmdPkW/0j2VAgMBAAGjggEMMIIB<br />
CDAdBgNVHQ4EFgQUXUSESsSBdTGjlbvo+Sbsiwo+E/4wgdgGA1UdIwSB0DCBzYAU<br />
XUSESsSBdTGjlbvo+Sbsiwo+E/6hgamkgaYwgaMxCzAJBgNVBAYTAkZSMQwwCgYD<br />
VQQIEwNSSEExFTATBgNVBAcTDFZpbGxldXJiYW5uZTEPMA0GA1UEChMGSUxMWVNF<br />
MRAwDgYDVQQLEwdvcGVudnBuMRowGAYDVQQDExFpbGx5c2Utb3BlbnZwbi1jYTEP<br />
MA0GA1UEKRMGSUxMWVNFMR8wHQYJKoZIhvcNAQkBFhBhYnVzZUBpbGx5c2Uub3Jn<br />
ggkA8BYrhx4QFfMwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAgEATAlP<br />
EQXjzQ10xkQdUNXjy+s87DWcbpu3n4Wlc4E828Ek6D1LhbPeVL7wTyhHj+Txxy8o<br />
4sCCL+oH/HgnMEy7VHs0HXpD3F9iPD8U3QiL1sfO+0IKOhBOKAsjmpuH+oCsXpZ0<br />
J/GnebPQ6S+wBFCZH3uU5jIeB4WCFpzn2WQVIXh+lzKKWLN3GxfxdWkIyl4Fluj4<br />
6k0Lj35EtE74wZTWbCkum7rNOp9gnGtrcyAupwj2MTeVcLzigYLth/G6AA3a7VeE<br />
hlvJqV7URhiwXL8lQjaMoDFYiD8zhBn44tLwKMiTvyHfNs0+1mcteoDwI20SKo3F<br />
VUnyCqc9k9Dq0YfE4RqhjmsMcV6HydaznCclnIrugPdFAQzGbk7bNZJ3yv0ATj9Z<br />
wcfHxIUEuPl392OvJDm/JEbegonQ4yyv2B8OAacZ4HPm/6FeYS/jyOe66BUku0rd<br />
LSVaB9OD7iVWkW5eo6ng3XA390HIUUtf/0IdtiCoMsjuZbVagfiaUu0kUJpR6d2k<br />
r5czdLFhRu8uw0sWn1rMQXlUAqH0WAfoq8XinaHesWs5MEnvevjoUTkNhFnqe1Ra<br />
rkwU9mzr1/N6GfpPalbveD0duTGAkJN5mwLZi+HZ4ctLgO1ShYFU/NbC7jNU3YCU<br />
sjvtdavgLFaMPLPrI2DAcjpVMUuL1VgdqUcQkhc=<br />
END CERTIFICATE—</p>
<p>&lt;/ca&gt;</p>
<h2 id="yunohost">Yunohost</h2>
<h3 id="installer-le-client-vpn">Installer le client VPN</h3>
<ul>
<li>Dans Applications &gt; Install, en bas de la page, entrer
https://github.com/labriqueinternet/vpnclient_ynh dans le champ
<strong>Install custom app</strong>.</li>
<li>Lire et valider lavertissement.</li>
<li>Valider linstallation en cliquant sur le bouton <strong>Install</strong></li>
</ul>
<h3 id="configurer-le-client-vpn">Configurer le client VPN</h3>
<h4 id="méthode-automatique-cube">Méthode automatique, “.cube”</h4>
<p>Le .cube est un fichier permettant de configurer lapplication
vpn-client automatiquement. Idéalement, ce fichier devrait être
automatiquement généré pour chaque adhérant dans notre SI, Coin. Ce
nest pour linstant pas encore le cas. Il faut donc faire son .cube à
la main, en utilisant la base suivante :</p>
<ul>
<li>télécharger le .cube de base:
<a href="https://doc.illyse.net/attachments/download/510/illyse.cube">illyse.cube</a></li>
<li>léditer avec nimporte quel éditeur de texte (notepad, gedit, nano,
vim, etc) afin de remplacer les 4 champs vous concernant: ip6_net,
ip4_addr, login_user, login_passphrase. Ces infos sont à
retrouver dans Coin (cf #Avant-de-commencer)</li>
<li>importer le .cube dans lapplication vpn_client (onglet “Automatic”
dans la configuration de lapplication)</li>
</ul>
<h4 id="méthode-manuelle">Méthode manuelle</h4>
<p>La méthode “.cube” décrite ci-dessus est vivement conseillée, car elle
permet de simplifier la procédure et déviter les erreurs. La méthode
manuelle est donnée uniquement à titre informatif.</p>
<ul>
<li>Dans Applications &gt; VPN Client, cliquer sur lURL
<a href="https://maBrique.nohost.me/vpnadmin"><em>https://maBrique.nohost.me/vpnadmin</em></a></li>
</ul>
<!-- -->
<ul>
<li>Server Address: vpn.illyse.net</li>
<li>Server Port: 1194</li>
<li>Protocol: UDP</li>
<li>Advanced: copier coller la configuration suivante:</li>
</ul>
<p>remote &lt;TPL:SERVER_NAME&gt;<br />
proto &lt;TPL:PROTO&gt;<br />
port &lt;TPL:SERVER_PORT&gt;<br />
pull<br />
nobind<br />
dev tun<br />
tun-ipv6<br />
keepalive 10 30<br />
resolv-retry infinite<br />
mssfix 1300<br />
route-delay 2<br />
nobind<br />
persist-key<br />
# Authentication by login<br />
&lt;TPL:LOGIN_COMMENT&gt;auth-user-pass /etc/openvpn/keys/credentials<br />
# UDP only<br />
&lt;TPL:UDP_COMMENT&gt;explicit-exit-notify<br />
&lt;TPL:UDP_COMMENT&gt;fragment 1300<br />
# TLS<br />
tls-client<br />
&lt;TPL:TA_COMMENT&gt;tls-auth /etc/openvpn/keys/user_ta.key 1<br />
remote-cert-tls server<br />
ns-cert-type server<br />
ca /etc/openvpn/keys/ca-server.crt<br />
&lt;TPL:CERT_COMMENT&gt;cert /etc/openvpn/keys/user.crt<br />
&lt;TPL:CERT_COMMENT&gt;key /etc/openvpn/keys/user.key<br />
# Logs<br />
verb 3<br />
mute 5<br />
status /var/log/openvpn-client.status<br />
log-append /var/log/openvpn-illyse.log<br />
# Routing<br />
route-ipv6 2000::/3<br />
redirect-gateway def1</p>
<ul>
<li>Server CA: Téléchargez le fichier
<a href="https://doc.illyse.net/attachments/download/437/vpn-illyse.crt">vpn-illyse.crt</a>
et le téléverser.</li>
<li>Username: pdupond-vpn1 (information issue de coin, cf section
#Avant-de-commencer)</li>
<li>Password: idem</li>
<li>First resolver: 80.67.169.12</li>
<li>2nd resolver : 2001:913::8</li>
</ul>
<p>Lensemble des autres champs est à laisser sur la valeur par défaut.</p>
<h1 id="configurations-avancées">Configurations avancées</h1>
<h2 id="client-sans-ip-montée-sur-le-tunnel">Client sans IP montée sur le tunnel</h2>
<p>Pour ceux qui veulent bricoler, il est possible (via linterface web
abonné) ne pas monter du tout dIP (v4 ou v6) sur linterface tun du
client. Dans ce cas, les paquets destinés aux ranges v4 et v6 de
labonné sont toujours routés correctement vers le client, mais il
appartient à labonné de sassurer quils seront correctement routés
plus avant sur son réseau interne. Ça peut être utile si on ne veut pas
utiliser lIPv4 publique Illyse directement sur le routeur qui monte le
VPN, mais sur une autre machine du réseau local.</p>
<p>Attention, si il ny a pas dIPv4 installée sur linterface tun, OpenVPN
est très bête et narrivera pas à installer la route par défaut par le
VPN… OpenVPN essaie dajouter des routes avec 89.234.140.129 comme
gateway, mais il ne sait pas joindre cette IP. Pour résoudre la
stupidité dOpenVPN\^W\^W\^W ce problème, on utilise un script qui
rajoute la route :</p>
<p>/etc/openvpn/illyse.conf</p>
<p><br />
route-delay 2<br />
redirect-gateway def1<br />
script-security 2<br />
up illyse-up.sh<br />
</p>
<p>/etc/openvpn/illyse-up.sh</p>
<p>#!/bin/sh<br />
tun_dev=”$1”<br />
ip link set “$tun_dev” up<br />
ip route add “$route_vpn_gateway” dev “$tun_dev”<br />
exit 0</p>
<h2 id="utiliser-simultanément-la-connexion-normale-et-le-vpn-sortie-par-défaut-par-la-connexion-normale">Utiliser simultanément la connexion normale et le VPN, sortie par défaut par la connexion normale</h2>
<p>Lorsquon a un serveur, on peut avoir envie dêtre joignable à la fois
via la connexion normale (e.g. Free) et via le VPN. Pour se faire, on
utilise le <strong>policy routing</strong> du noyau Linux : quand quelquun nous
parle sur lIP normale, on lui répond via la connexion normale, et quand
quelquun nous parle sur lIP du VPN, on répond via le VPN. Notons que
ça ne concerne que les connexions entrantes (donc principalement utile
pour un serveur).</p>
<p>Pour les connexions sortantes, on a le choix : soit on passe dans le
VPN, soit on passe par la connexion normale. La configuration ci-dessous
fait passer les connexions sortantes par la connexion normale (parce que
cest plus simple).</p>
<p>Note : il faut sassurer de bien avoir configuré une IPv4 et une IPv6
sur linterface tun (sur
<a href="https://coin.illyse.org/">https://coin.illyse.org</a>). Sinon, les scripts
ne feront rien.</p>
<p>Bonus : si vous avez un noyau Multipath-TCP, cette configuration
permettra dutiliser les deux connexions en parallèle ! Pratique pour
joindre Youtube si on est chez Free, par exemple :)<br />
(la configuration ci-dessous est similaire à
<a href="http://multipath-tcp.org/pmwiki.php/Users/ConfigureRouting">http://multipath-tcp.org/pmwiki.php/Users/ConfigureRouting</a> )</p>
<p>/etc/openvpn/up.sh</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#!/bin/bash
dev="$1"
tun_mtu="$2"
link_mtu="$3"
local_ip="$4"
remote_ip="$5"
# Routing table to use
table=4242
# Source-specific routing: use the normal default route by default,
# but use the VPN for replying to packets coming from the VPN.
# IPv4
[ -n "$local_ip" ] &amp;&amp; ip rule add from "$local_ip" table "$table" &amp;&amp; ip route add default dev "$dev" table "$table"
# IPv6
[ -n "$ifconfig_ipv6_local" ] &amp;&amp; ip -6 rule add from "$ifconfig_ipv6_local" table "$table" &amp;&amp; ip -6 route add default dev "$dev" table "$table"
</code></pre></div></div>
<p>/etc/openvpn/down.sh</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#!/bin/bash
dev="$1"
tun_mtu="$2"
link_mtu="$3"
local_ip="$4"
remote_ip="$5"
table=4242
# Delete table for source-specific routing.
[ -n "$local_ip" ] &amp;&amp; ip rule del from "$local_ip" &amp;&amp; ip route del default table "$table"
[ -n "$ifconfig_ipv6_local" ] &amp;&amp; ip -6 rule del from "$ifconfig_ipv6_local" &amp;&amp; ip -6 route del default table "$table"
exit 0
</code></pre></div></div>
<p>/etc/openvpn/illyse.conf</p>
<p>## Configuration VPN Illyse pour accepter des connexions entrantes<br />
## à la fois via le VPN et via la connexion normale, grâce au policy
routing (Linux uniquement)<br />
##
https://www.illyse.org/projects/publicdocs/wiki/Vpn_doc_user#Utiliser-simultanément-la-connexion-normale-et-le-VPN<br />
# Gestion des routes via des scripts externes.<br />
script-security 2<br />
up up.sh<br />
down down.sh<br />
# Reste de la configuration normale.<br />
# Penser à enlever “redirect-gateway” et “route-ipv6”, on gère les<br />
# routes via up.sh et down.sh<br />
client<br />
remote vpn.illyse.net 1194<br />
#http-proxy 192.0.2.1 8080<br />
dev tun0<br />
#proto udp6<br />
proto udp<br />
#proto tcp<br />
explicit-exit-notify<br />
mssfix 1300<br />
fragment 1300<br />
route-delay 2<br />
nobind<br />
persist-key<br />
persist-tun<br />
tun-ipv6<br />
auth-user-pass credentials<br />
verb 3<br />
log-append /var/log/openvpn-illyse.log<br />
# Certificat permettant de vérifier que cest bien à Illyse que<br />
# lon se connecte et donc à qui on donne notre mot de passe.<br />
remote-cert-tls server</p>
<p>&lt;ca&gt;</p>
<p>BEGIN CERTIFICATE—<br />
MIIG2TCCBMGgAwIBAgIJAPAWK4ceEBXzMA0GCSqGSIb3DQEBBQUAMIGjMQswCQYD<br />
VQQGEwJGUjEMMAoGA1UECBMDUkhBMRUwEwYDVQQHEwxWaWxsZXVyYmFubmUxDzAN<br />
BgNVBAoTBklMTFlTRTEQMA4GA1UECxMHb3BlbnZwbjEaMBgGA1UEAxMRaWxseXNl<br />
LW9wZW52cG4tY2ExDzANBgNVBCkTBklMTFlTRTEfMB0GCSqGSIb3DQEJARYQYWJ1<br />
c2VAaWxseXNlLm9yZzAeFw0xNDAzMTgyMTMyMjNaFw0yNDAzMTUyMTMyMjNaMIGj<br />
MQswCQYDVQQGEwJGUjEMMAoGA1UECBMDUkhBMRUwEwYDVQQHEwxWaWxsZXVyYmFu<br />
bmUxDzANBgNVBAoTBklMTFlTRTEQMA4GA1UECxMHb3BlbnZwbjEaMBgGA1UEAxMR<br />
aWxseXNlLW9wZW52cG4tY2ExDzANBgNVBCkTBklMTFlTRTEfMB0GCSqGSIb3DQEJ<br />
ARYQYWJ1c2VAaWxseXNlLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC<br />
ggIBAKl/s6IoAsJTxw82xps5PHPTMjKhONFNk4gJMdSngbhGMcRM5ebwD9Dhfava<br />
w9NjWiwNhikhnRWW3HGrv+BE7cqga16ryuLCievG1nfqZMpa3EnfWwwmHClMV9Zf<br />
OPb/AD2V3t2MAvZ1ZcvyTe/p/3eHovHhEHJ2qXtd0iI9u8b7xcEm9vXIw7kYN2dQ<br />
xIe9Wd85tja2IBtf67oBS8JZxSkIcEY7KAXsFUtFyGn6fbPGj8UGM+roiYqzEYa/<br />
BNvc2eEfhhpHSoN5vRKu0LrVUA3uA41dOKcxW15af4Xy058l0aUWeSK64jK/cL24<br />
fmBZoQfdS9U5P5wnm4tpRR7oesdrohhbVWn4JjRyF31HM1FtAoT6oTqhhlrImpGw<br />
j7nAGlItT04C73wgiSajFJryo24XuedzjFxm3BetAcSUyE5e3BSqTUbEtWdTdiw1<br />
l3/WQyyBrn98SChBExmpklecI5eFp/DoLBqwW/U/vseD7zMfF7OHnHtbsbniUujN<br />
WjNGiWnVJ636nTfPIDsngGTACWh5ZwxX0fGW2+RqS2NN9R1dGWdW34lgfwx04Wzc<br />
l0NZ++itmJq5iJUw9Kj9mmQZn96V8b6hDnhcJfkvUlgxhHcZ5isfOwQq6UcP3mZP<br />
zOCWuCwIKNPMLcJmC684mkJJrJuCc6N9pNm7jjmdPkW/0j2VAgMBAAGjggEMMIIB<br />
CDAdBgNVHQ4EFgQUXUSESsSBdTGjlbvo+Sbsiwo+E/4wgdgGA1UdIwSB0DCBzYAU<br />
XUSESsSBdTGjlbvo+Sbsiwo+E/6hgamkgaYwgaMxCzAJBgNVBAYTAkZSMQwwCgYD<br />
VQQIEwNSSEExFTATBgNVBAcTDFZpbGxldXJiYW5uZTEPMA0GA1UEChMGSUxMWVNF<br />
MRAwDgYDVQQLEwdvcGVudnBuMRowGAYDVQQDExFpbGx5c2Utb3BlbnZwbi1jYTEP<br />
MA0GA1UEKRMGSUxMWVNFMR8wHQYJKoZIhvcNAQkBFhBhYnVzZUBpbGx5c2Uub3Jn<br />
ggkA8BYrhx4QFfMwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAgEATAlP<br />
EQXjzQ10xkQdUNXjy+s87DWcbpu3n4Wlc4E828Ek6D1LhbPeVL7wTyhHj+Txxy8o<br />
4sCCL+oH/HgnMEy7VHs0HXpD3F9iPD8U3QiL1sfO+0IKOhBOKAsjmpuH+oCsXpZ0<br />
J/GnebPQ6S+wBFCZH3uU5jIeB4WCFpzn2WQVIXh+lzKKWLN3GxfxdWkIyl4Fluj4<br />
6k0Lj35EtE74wZTWbCkum7rNOp9gnGtrcyAupwj2MTeVcLzigYLth/G6AA3a7VeE<br />
hlvJqV7URhiwXL8lQjaMoDFYiD8zhBn44tLwKMiTvyHfNs0+1mcteoDwI20SKo3F<br />
VUnyCqc9k9Dq0YfE4RqhjmsMcV6HydaznCclnIrugPdFAQzGbk7bNZJ3yv0ATj9Z<br />
wcfHxIUEuPl392OvJDm/JEbegonQ4yyv2B8OAacZ4HPm/6FeYS/jyOe66BUku0rd<br />
LSVaB9OD7iVWkW5eo6ng3XA390HIUUtf/0IdtiCoMsjuZbVagfiaUu0kUJpR6d2k<br />
r5czdLFhRu8uw0sWn1rMQXlUAqH0WAfoq8XinaHesWs5MEnvevjoUTkNhFnqe1Ra<br />
rkwU9mzr1/N6GfpPalbveD0duTGAkJN5mwLZi+HZ4ctLgO1ShYFU/NbC7jNU3YCU<br />
sjvtdavgLFaMPLPrI2DAcjpVMUuL1VgdqUcQkhc=<br />
END CERTIFICATE—</p>
<p>&lt;/ca&gt;</p>
<h2 id="utiliser-simultanément-la-connexion-normale-et-le-vpn-sortie-par-défaut-via-le-vpn">Utiliser simultanément la connexion normale et le VPN, sortie par défaut via le VPN</h2>
<p>Dans la configuration précédente, les deux IPs, FAI et VPN, sont
accessibles de lextérieur et répondent correctement.<br />
La machine toutefois utilise par défaut la sortie FAI plutôt que le
VPN.<br />
Le cas décrit ici a son IP FAI obtenue par DHCP, avec la table de
routage main, et sans IPv6.<br />
Il faut bidouiller les routes pour que si on contacte lIP du serveur
VPN, on passe bien par lIP FAI et linterface qui correspond, puis
répondre à ce qui vient de lIP FAI par la table main, et enfin par
défaut sortir par le table correspondant au VPN.</p>
<p>Étape 1, dans le fichier illyse.conf, il faut ajouter loption
ifconfig-noexec pour éviter quopenVPN ne monte lIP du VPN avant
quon ne gère ça dans le script up.sh<br />
Étape 2, changer les scripts up.sh et down.s. Actuellement, on na pas
trouvé de solution propre pour éviter de coder en dur des paramètres
dans ce scripts.<br />
/etc/openvpn/up.conf</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#!/bin/bash
dev="$1"
isp_dev="eth0"
tun_mtu="$2"
link_mtu="$3"
local_ip="$4"
remote_ip="$5"
isp_ip="WWW.XXX.YYY.ZZZ"
isp_gateway="WWW.XXX.YYY.ZZZ"
vpn_server="89.234.140.3"
# Routing table to use
tableVPN=4242
tableLOC=1337
# IP inconnue de COIN, donc tun0 à monter
ip link set "$dev" up
ip addr add "$local_ip"/32 dev "$dev"
# Source-specific routing: use the normal default route by default,
# but use the VPN for replying to packets coming from the VPN.
# IPv4
if [ -n "local_ip" ]; then
ip rule add pref 31000 lookup "$tableLOC"
ip rule add pref 31050 from "$isp_ip" lookup main
ip rule add pref 31100 lookup "$tableVPN"
ip route add default dev "$dev" table "$tableVPN"
ip route add "$vpn_server" via "$isp_gateway" table "$tableLOC" dev "$isp_dev"
fi
# IPv6
[ -n "$ifconfig_ipv6_local" ] &amp;&amp; ip -6 addr add "$ifconfig_ipv6_local" dev "$dev" &amp;&amp; ip -6 route add default dev "$dev"
exit 0
</code></pre></div></div>
<p>/etc/openvpn/down.conf</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dev="$1"
tun_mtu="$2"
link_mtu="$3"
local_ip="$4"
remote_ip="$5"
isp_ip="WWW.XXX.YYY.ZZZ"
isp_gateway="WWW.XXX.YYY.ZZZ"
vpn_server="89.234.140.3"
# Routing table to use
tableVPN=4242
tableLOC=1337
# Delete table for source-specific routing.
if [ "$local_ip" ]; then
ip route del "$vpn_server" via "$isp_gateway" table "$tableLOC"
ip route del default dev "$dev" table "$tableVPN"
ip rule del pref 31100 lookup "$tableVPN"
ip rule del pref 31050 from "$isp_ip" lookup main
ip rule del pref 31000 lookup "$tableLOC"
fi
[ -n "$ifconfig_ipv6_local" ] &amp;&amp; ip -6 route del default dev "$dev" &amp;&amp; ip -6 addr del "$ifconfig_ipv6_local" dev "$dev"
exit 0
</code></pre></div></div>
<h3 id="utiliser-simultanément-la-connexion-normale-et-le-vpn-sortie-par-défaut-via-le-vpn-et-faire-ap-wifi">Utiliser simultanément la connexion normale et le VPN, sortie par défaut via le VPN, et faire AP WiFi</h3>
<p>On a foutu le bordel dans les routes, ce qui fait que hostapd narrive
pas à faire tomber le bousin en marche, car il met ses routes dans la
table main au lieu de les mettre dans la tableVPN 4242.<br />
Du coup, on laide (en supposant que le wlan soit en 192.168.2.0/24) :</p>
<p>ip route del 192.168.2.0/24 dev wlan0 table main<br />
ip route add 192.168.2.0/24 dev wlan0 table 4242</p>
<p>Il ne reste plus quà activer le NAT sur linterface tun0 du VPN et
paf ! On fait un beau AP WiFi (vilainement naté) qui fournit une
connexion Illyse.</p>
<p><a href="https://doc.illyse.net/attachments/download/353/vpn1.png">vpn1.png</a>
(40,5 ko) Côme chillie, 06/10/2015 00:20<br />
<a href="https://doc.illyse.net/attachments/download/354/vpn2.png">vpn2.png</a>
(39,3 ko) Côme chillie, 06/10/2015 00:20<br />
<a href="https://doc.illyse.net/attachments/download/437/vpn-illyse.crt">vpn-illyse.crt</a></p>
<ul>
<li>Certificat serveur VPN (2,38 ko) Florent Guillot, 07/02/2016 19:41<br />
<a href="https://doc.illyse.net/attachments/download/510/illyse.cube">illyse.cube</a>
(2,97 ko) Florent Guillot, 23/06/2016 20:18</li>
</ul>
<h2 id="fichier-cube">Fichier .cube</h2>
<p>Un fichier .cube nest quun fichier Json. Les sections suivantes ont pour but dexpliquer aux fournisseurs de VPN comment créer des fichiers .cubes pour leurs membres.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>{
"server_name": "vpn.ldn-fai.net",
"server_port": "1194",
"server_proto": "udp",
"ip6_net": "2001:db8:c42::",
"ip4_addr": "203.0.113.42",
"crt_server_ca": "-----BEGIN CERTIFICATE-----|MIIFFXAJjzZhAZJ+JHA…eRte6K|-----END CERTIFICATE-----",
"crt_client": "-----BEGIN CERTIFICATE-----|MIIFbUHHQjauIUoiUAA5ax…4T3As=|-----END CERTIFICATE-----",
"crt_client_key": "-----BEGIN PRIVATE KEY-----|MIIEvM/JsSAmledzvE…i8kAMj|-----END PRIVATE KEY-----",
"crt_client_ta": "",
"login_user": "",
"login_passphrase": "",
"dns0": "89.234.141.66",
"dns1": "2001:913::8",
"openvpn_rm": [ ],
"openvpn_add": [ "topology subnet" ]
}
</code></pre></div></div>
</div>
<div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2019-12-25T00:00:00+01: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="/2019/12/25/https-tor-vpn-de-quoi-est-ce-que-ca-protege-exactement.html">https-tor-vpn-de-quoi-est-ce-que-ca-protege-exactement</a></div><div class="next"><span>SUIVANT</span><a href="/2019/12/25/install_archlinux_with_encrypted_filesystem_and__uefi.html">install_archlinux_with_encrypted_filesystem_and _uefi</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>